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:28 UTC
[1/9] incubator-geode git commit: Add awaitility
Repository: incubator-geode
Updated Branches:
refs/heads/feature/GEODE-217 [created] c396e94a1
Add awaitility
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/8c4c3e07
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/8c4c3e07
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/8c4c3e07
Branch: refs/heads/feature/GEODE-217
Commit: 8c4c3e07b85857a1c19956a9893a5bcec213343f
Parents: 2914567
Author: Kirk Lund <kl...@pivotal.io>
Authored: Fri Aug 14 10:21:56 2015 -0700
Committer: Kirk Lund <kl...@pivotal.io>
Committed: Fri Aug 14 10:21:56 2015 -0700
----------------------------------------------------------------------
build.gradle | 1 +
1 file changed, 1 insertion(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/8c4c3e07/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 42b4a14..729f1b0 100755
--- a/build.gradle
+++ b/build.gradle
@@ -276,6 +276,7 @@ subprojects {
compile 'org.springframework:spring-webmvc:3.2.12.RELEASE'
testCompile 'com.github.stefanbirkner:system-rules:1.9.0'
+ testCompile 'com.jayway.awaitility:awaitility:1.6.3'
testCompile 'edu.umd.cs.mtc:multithreadedtc:1.01'
testCompile 'junit:junit:4.12'
testCompile 'org.mockito:mockito-core:1.10.19'
[2/9] incubator-geode git commit: Add testing frameworks for junit
tests.
Posted by kl...@apache.org.
Add testing frameworks for junit tests.
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/fb5452ad
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/fb5452ad
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/fb5452ad
Branch: refs/heads/feature/GEODE-217
Commit: fb5452ad1c1a77f4ff603afef20de7ecd6fd5b3a
Parents: 8c4c3e0
Author: Kirk Lund <kl...@pivotal.io>
Authored: Sat Aug 15 17:48:04 2015 -0700
Committer: Kirk Lund <kl...@pivotal.io>
Committed: Sat Aug 15 17:48:04 2015 -0700
----------------------------------------------------------------------
build.gradle | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fb5452ad/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 729f1b0..0311206 100755
--- a/build.gradle
+++ b/build.gradle
@@ -278,13 +278,19 @@ subprojects {
testCompile 'com.github.stefanbirkner:system-rules:1.9.0'
testCompile 'com.jayway.awaitility:awaitility:1.6.3'
testCompile 'edu.umd.cs.mtc:multithreadedtc:1.01'
+ testCompile 'eu.codearte.catch-exception:catch-exception:1.4.4'
+ testCompile 'eu.codearte.catch-exception:catch-throwable:1.4.4'
testCompile 'junit:junit:4.12'
+ testCompile 'org.assertj:assertj-core:2.1.0'
+ testCompile 'org.easytesting:fest-test:2.1.0'
testCompile 'org.mockito:mockito-core:1.10.19'
testCompile 'org.hamcrest:hamcrest-all:1.3'
testCompile 'org.jmock:jmock:2.8.1'
testCompile 'org.jmock:jmock-junit4:2.8.1'
testCompile 'org.jmock:jmock-legacy:2.8.1'
-
+ testCompile 'org.unitils:unitils:3.4.2'
+ testCompile 'pl.pragmatists:JUnitParams:1.0.4'
+
testRuntime 'cglib:cglib:3.1'
testRuntime 'org.objenesis:objenesis:2.1'
testRuntime 'org.ow2.asm:asm:5.0.3'
[5/9] incubator-geode git commit: Dunit changes for JUnit 4 syntax.
Refactoring to modernize API.
Posted by kl...@apache.org.
Dunit changes for JUnit 4 syntax. Refactoring to modernize API.
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/49b2913a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/49b2913a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/49b2913a
Branch: refs/heads/feature/GEODE-217
Commit: 49b2913aca753b408dac556371ea700c81d909f0
Parents: fb5452a
Author: Kirk Lund <kl...@pivotal.io>
Authored: Sat Aug 15 17:49:06 2015 -0700
Committer: Kirk Lund <kl...@pivotal.io>
Committed: Sat Aug 15 17:49:06 2015 -0700
----------------------------------------------------------------------
.../gemfire/internal/util/DebuggerSupport.java | 16 +-
.../distributed/DistributedMemberDUnitTest.java | 399 +++---
.../distributed/HostedLocatorsDUnitTest.java | 70 +-
.../distributed/MembershipTestSuite.java | 17 +
.../offheap/OutOfOffHeapMemoryDUnitTest.java | 88 +-
.../catchexception/CatchExceptionDUnitTest.java | 63 +
.../catchexception/CatchExceptionJUnitTest.java | 95 ++
.../com/gemstone/gemfire/test/dunit/Assert.java | 11 +
.../gemfire/test/dunit/AsyncInvocation.java | 206 +++
.../gemfire/test/dunit/BounceResult.java | 20 +
.../gemstone/gemfire/test/dunit/DUnitEnv.java | 68 +
.../gemfire/test/dunit/DebuggerSupport.java | 20 +
.../gemfire/test/dunit/DistributedTestCase.java | 659 +++++++++
.../test/dunit/ExpectedExceptionString.java | 142 ++
.../com/gemstone/gemfire/test/dunit/Host.java | 201 +++
.../com/gemstone/gemfire/test/dunit/Invoke.java | 146 ++
.../com/gemstone/gemfire/test/dunit/Jitter.java | 70 +
.../gemfire/test/dunit/RMIException.java | 161 +++
.../gemfire/test/dunit/RemoteDUnitVMIF.java | 18 +
.../gemfire/test/dunit/RepeatableRunnable.java | 13 +
.../test/dunit/SerializableCallable.java | 61 +
.../test/dunit/SerializableRunnable.java | 83 ++
.../test/dunit/StoppableWaitCriterion.java | 12 +
.../gemstone/gemfire/test/dunit/ThreadDump.java | 157 +++
.../com/gemstone/gemfire/test/dunit/VM.java | 1333 ++++++++++++++++++
.../com/gemstone/gemfire/test/dunit/Wait.java | 167 +++
.../gemfire/test/dunit/WaitCriterion.java | 11 +
.../gemfire/test/dunit/cache/CacheTestCase.java | 696 +++++++++
.../gemfire/test/dunit/standalone/ChildVM.java | 62 +
.../test/dunit/standalone/DUnitLauncher.java | 416 ++++++
.../test/dunit/standalone/ProcessManager.java | 228 +++
.../test/dunit/standalone/RemoteDUnitVM.java | 136 ++
.../dunit/standalone/StandAloneDUnitEnv.java | 66 +
.../test/dunit/tests/BasicDUnitTest.java | 124 ++
.../dunit/tests/DUnitFrameworkTestSuite.java | 16 +
.../gemfire/test/dunit/tests/TestFailure.java | 37 +
.../gemfire/test/dunit/tests/VMDUnitTest.java | 245 ++++
.../test/java/dunit/DistributedTestCase.java | 6 +-
gemfire-core/src/test/java/dunit/VM.java | 2 -
.../java/dunit/standalone/ProcessManager.java | 2 +-
.../test/junit/categories/MembershipTest.java | 9 +
41 files changed, 6079 insertions(+), 273 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/DebuggerSupport.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/DebuggerSupport.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/DebuggerSupport.java
index c40df4d..f7d4fcb 100644
--- a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/DebuggerSupport.java
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/util/DebuggerSupport.java
@@ -8,8 +8,11 @@
package com.gemstone.gemfire.internal.util;
-import com.gemstone.gemfire.i18n.LogWriterI18n;
+import org.apache.logging.log4j.Logger;
+
import com.gemstone.gemfire.internal.i18n.LocalizedStrings;
+import com.gemstone.gemfire.internal.logging.LogService;
+import com.gemstone.gemfire.internal.logging.log4j.LocalizedMessage;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
@@ -19,23 +22,24 @@ import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
*
*/
public abstract class DebuggerSupport {
+ private static final Logger logger = LogService.getLogger();
/** Creates a new instance of DebuggerSupport */
private DebuggerSupport() {
}
/** Debugger support */
- public static void waitForJavaDebugger(LogWriterI18n logger) {
- waitForJavaDebugger(logger, null);
+ public static void waitForJavaDebugger() {
+ waitForJavaDebugger(null);
}
@SuppressFBWarnings(value="IL_INFINITE_LOOP", justification="Endless loop is for debugging purposes.")
- public static void waitForJavaDebugger(LogWriterI18n logger, String extraLogMsg) {
+ public static void waitForJavaDebugger(String extraLogMsg) {
boolean cont = false;
String msg = ":";
if (extraLogMsg != null)
msg += extraLogMsg;
- logger.severe(LocalizedStrings.DebuggerSupport_WAITING_FOR_DEBUGGER_TO_ATTACH_0, msg);
+ logger.fatal(LocalizedMessage.create(LocalizedStrings.DebuggerSupport_WAITING_FOR_DEBUGGER_TO_ATTACH_0, msg));
boolean interrupted = false;
while (!cont) { // set cont to true in debugger when ready to continue
try {
@@ -50,6 +54,6 @@ public abstract class DebuggerSupport {
if (interrupted) {
Thread.currentThread().interrupt();
}
- logger.info(LocalizedStrings.DebuggerSupport_DEBUGGER_CONTINUING);
+ logger.info(LocalizedMessage.create(LocalizedStrings.DebuggerSupport_DEBUGGER_CONTINUING));
}
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/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 dd35794..e45b02d 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,16 +7,48 @@
*/
package com.gemstone.gemfire.distributed;
+import static java.util.concurrent.TimeUnit.*;
+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.*;
-import dunit.*;
+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.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.Callable;
+
+import org.junit.After;
+import org.junit.Before;
+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.distributed.internal.membership.*;
-import junit.framework.AssertionFailedError;
+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.Host;
+import com.gemstone.gemfire.test.dunit.RMIException;
+import com.gemstone.gemfire.test.dunit.SerializableCallable;
+import com.gemstone.gemfire.test.dunit.SerializableRunnable;
+import com.gemstone.gemfire.test.dunit.VM;
/**
* Tests the functionality of the {@link DistributedMember} class.
@@ -24,137 +56,132 @@ import junit.framework.AssertionFailedError;
* @author Kirk Lund
* @since 5.0
*/
+@SuppressWarnings("serial")
+@Category({ DistributedTest.class, MembershipTest.class })
public class DistributedMemberDUnitTest extends DistributedTestCase {
- public DistributedMemberDUnitTest(String name) {
- super(name);
+ private Properties config;
+
+ @Rule
+ public final transient ExpectedException expectedException = ExpectedException.none();
+
+ @Rule
+ public final transient ConditionalIgnoreRule ignoreRule = new ConditionalIgnoreRule();
+
+ @BeforeClass
+ public static void beforeClass() {
+ disconnectAllFromDS();
}
- protected void sleep(long millis) {
- try {
- Thread.sleep(millis);
- }
- catch (InterruptedException e) {
- fail("interrupted");
- }
+ @Before
+ public void setUp() {
+ this.config = createConfig();
}
+ @After
+ public void tearDown() {
+ disconnectAllFromDS();
+ }
+
/**
- * Tests default settings.
+ * Tests default configuration values.
*/
- public void testDefaults() {
- Properties config = new Properties();
- config.setProperty(DistributionConfig.MCAST_PORT_NAME, "0");
- config.setProperty(DistributionConfig.LOCATORS_NAME, "");
- config.setProperty(DistributionConfig.ROLES_NAME, "");
- config.setProperty(DistributionConfig.GROUPS_NAME, "");
- config.setProperty(DistributionConfig.NAME_NAME, "");
+ @Test
+ public void defaultConfigShouldHaveEmptyValues() {
+ // arrange
+ this.config.setProperty(DistributionConfig.LOCATORS_NAME, "");
+ this.config.setProperty(DistributionConfig.ROLES_NAME, "");
+ this.config.setProperty(DistributionConfig.GROUPS_NAME, "");
+ this.config.setProperty(DistributionConfig.NAME_NAME, "");
- InternalDistributedSystem system = getSystem(config);
- try {
- assertTrue(system.getConfig().getRoles().equals(
- DistributionConfig.DEFAULT_ROLES));
- assertTrue(system.getConfig().getGroups().equals(
- DistributionConfig.DEFAULT_ROLES));
- assertTrue(system.getConfig().getName().equals(
- DistributionConfig.DEFAULT_NAME));
+ // act
+ final InternalDistributedSystem system = getSystem(this.config);
+ final InternalDistributedMember member = system.getDistributedMember();
- DM dm = system.getDistributionManager();
- InternalDistributedMember member = dm.getDistributionManagerId();
-
- Set roles = member.getRoles();
- assertEquals(0, roles.size());
- assertEquals("", member.getName());
- assertEquals(Collections.emptyList(), member.getGroups());
- }
- finally {
- system.disconnect();
- }
+ // assert
+ assertThat(system.getConfig().getRoles(), is(DistributionConfig.DEFAULT_ROLES));
+ assertThat(system.getConfig().getGroups(), is(DistributionConfig.DEFAULT_ROLES));
+ assertThat(system.getConfig().getName(), is(DistributionConfig.DEFAULT_NAME));
+
+ assertThat(member.getRoles(), is(empty()));
+ assertThat(member.getName(), isEmptyString());
+ assertThat(member.getGroups(), is(empty()));
}
- public void testNonDefaultName() {
- Properties config = new Properties();
- config.setProperty(DistributionConfig.MCAST_PORT_NAME, "0");
- config.setProperty(DistributionConfig.LOCATORS_NAME, "");
- config.setProperty(DistributionConfig.NAME_NAME, "nondefault");
+ @Test
+ public void nameShouldBeUsed() {
+ // arrange
+ this.config.setProperty(DistributionConfig.LOCATORS_NAME, "");
+ this.config.setProperty(DistributionConfig.NAME_NAME, "nondefault");
- InternalDistributedSystem system = getSystem(config);
- try {
- assertEquals("nondefault", system.getConfig().getName());
+ // act
+ final InternalDistributedSystem system = getSystem(this.config);
+ final InternalDistributedMember member = system.getDistributedMember();
- DM dm = system.getDistributionManager();
- InternalDistributedMember member = dm.getDistributionManagerId();
-
- assertEquals("nondefault", member.getName());
- }
- finally {
- system.disconnect();
- }
+ // assert
+ assertThat(system.getConfig().getName(), is("nondefault"));
+ assertThat(member.getName(), is("nondefault"));
}
/**
* Tests the configuration of many Roles and groups in one vm.
* Confirms no runtime distinction between roles and groups.
*/
- public void testRolesInOneVM() {
- final String rolesProp = "A,B,C";
- final String groupsProp = "D,E,F,G";
- final List bothList = Arrays.asList(new String[] {"A","B","C","D","E","F","G"});
+ @Test
+ public void multipleRolesAndGroupsAreUsed() {
+ // arrange
+ final String roles = "A,B,C";
+ final String groups = "D,E,F,G";
+ final List<String> rolesAndGroups = Arrays.asList((roles+","+groups).split(","));
- Properties config = new Properties();
- config.setProperty(DistributionConfig.MCAST_PORT_NAME, "0");
- config.setProperty(DistributionConfig.LOCATORS_NAME, "");
- config.setProperty(DistributionConfig.ROLES_NAME, rolesProp);
- config.setProperty(DistributionConfig.GROUPS_NAME, groupsProp);
+ this.config.setProperty(DistributionConfig.LOCATORS_NAME, "");
+ this.config.setProperty(DistributionConfig.ROLES_NAME, roles);
+ this.config.setProperty(DistributionConfig.GROUPS_NAME, groups);
- InternalDistributedSystem system = getSystem(config);
- try {
- assertEquals(rolesProp, system.getConfig().getRoles());
- assertEquals(groupsProp, system.getConfig().getGroups());
-
- DM dm = system.getDistributionManager();
- InternalDistributedMember member = dm.getDistributionManagerId();
-
- Set roles = member.getRoles();
- assertEquals(bothList.size(), roles.size());
-
- for (Iterator iter = roles.iterator(); iter.hasNext();) {
- Role role = (Role) iter.next();
- assertTrue(bothList.contains(role.getName()));
- }
-
- assertEquals(bothList, member.getGroups());
- }
- finally {
- system.disconnect();
+ // act
+ final InternalDistributedSystem system = getSystem(this.config);
+ final InternalDistributedMember member = system.getDistributedMember();
+
+ // assert
+ assertThat(system.getConfig().getRoles(), is(roles));
+ assertThat(system.getConfig().getGroups(), is(groups));
+ assertThat(member.getRoles().size(), is(rolesAndGroups.size()));
+ for (Role role : member.getRoles()) {
+ assertThat(role.getName(), isIn(rolesAndGroups));
}
+ assertThat(member.getGroups(), is(rolesAndGroups));
}
- public void testTwoMembersSameName() {
- disconnectFromDS(); // or assertion on # members fails when run-dunit-tests
+ @Test
+ public void secondMemberUsingSameNameShouldFail() {
Host.getHost(0).getVM(0).invoke(new SerializableRunnable() {
public void run() {
- Properties config = new Properties();
+ Properties config = createConfig();
config.setProperty(DistributionConfig.NAME_NAME, "name0");
getSystem(config);
}
});
Host.getHost(0).getVM(1).invoke(new SerializableRunnable() {
public void run() {
- Properties config = new Properties();
+ Properties config = createConfig();
config.setProperty(DistributionConfig.NAME_NAME, "name1");
getSystem(config);
}
});
+
+ expectedException.expect(RMIException.class);
+ expectedException.expectCause(isA(IncompatibleSystemException.class));
+ //expectedException.expectMessage("used the same name");
+
Host.getHost(0).getVM(2).invoke(new SerializableRunnable() {
public void run() {
- Properties config = new Properties();
+ Properties config = createConfig();
config.setProperty(DistributionConfig.NAME_NAME, "name0");
- try {
+// try {
getSystem(config);
- fail("expected IncompatibleSystemException");
- } catch (IncompatibleSystemException expected) {
- }
+// fail("expected IncompatibleSystemException");
+// } catch (IncompatibleSystemException expected) {
+// }
}
});
}
@@ -163,17 +190,15 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
* Tests the configuration of one unique Role in each of four vms. Verifies
* that each vm is aware of the other vms' Roles.
*/
- public void testRolesInAllVMs() {
- disconnectAllFromDS(); // or assertion on # members fails when run-dunit-tests
-
+ @Test
+ public void allMembersShouldSeeRoles() {
// connect all four vms...
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;
Host.getHost(0).getVM(vm).invoke(new SerializableRunnable() {
public void run() {
- //disconnectFromDS();
- Properties config = new Properties();
+ Properties config = createConfig();
config.setProperty(DistributionConfig.ROLES_NAME, vmRoles[vm]);
getSystem(config);
}
@@ -189,36 +214,23 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
assertNotNull(sys.getConfig().getRoles());
assertTrue(sys.getConfig().getRoles().equals(vmRoles[vm]));
- DM dm = sys.getDistributionManager();
- InternalDistributedMember self = dm.getDistributionManagerId();
+ InternalDistributedMember self = sys.getDistributedMember();
- Set myRoles = self.getRoles();
+ Set<Role> myRoles = self.getRoles();
assertEquals(1, myRoles.size());
Role myRole = (Role) myRoles.iterator().next();
assertTrue(vmRoles[vm].equals(myRole.getName()));
- Set members = null;
- for (int i = 1; i <= 3; i++) {
- try {
- members = dm.getOtherNormalDistributionManagerIds();
- assertEquals(3, members.size());
- break;
- }
- catch (AssertionFailedError e) {
- if (i < 3) {
- sleep(200);
- } else {
- throw e;
- }
- }
- }
+ with().pollInterval(TWO_HUNDRED_MILLISECONDS).await().atMost(60, SECONDS).until( numberOfOtherMembers(), equalTo(3) );
+ // used to have a for-loop here
- for (Iterator iterMembers = members.iterator(); iterMembers.hasNext();) {
- InternalDistributedMember member = (InternalDistributedMember) iterMembers.next();
- Set roles = member.getRoles();
+ Set<InternalDistributedMember> members = sys.getDM().getOtherNormalDistributionManagerIds();
+ for (Iterator<InternalDistributedMember> iterMembers = members.iterator(); iterMembers.hasNext();) {
+ InternalDistributedMember member = iterMembers.next();
+ Set<Role> roles = member.getRoles();
assertEquals(1, roles.size());
- for (Iterator iterRoles = roles.iterator(); iterRoles.hasNext();) {
+ for (Iterator<Role> iterRoles = roles.iterator(); iterRoles.hasNext();) {
Role role = (Role) iterRoles.next();
assertTrue(!role.getName().equals(myRole.getName()));
boolean foundRole = false;
@@ -236,26 +248,26 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
}
}
- private static String makeOddEvenString(int vm) {
- return ((vm % 2) == 0) ? "EVENS" : "ODDS";
- }
- private static String makeGroupsString(int vm) {
- return "" + vm + ", " + makeOddEvenString(vm);
+ private Callable<Integer> numberOfOtherMembers() {
+ return new Callable<Integer>() {
+ public Integer call() throws Exception {
+ return getSystem().getDM().getOtherNormalDistributionManagerIds().size();
+ }
+ };
}
+
/**
* Tests the configuration of one unique group in each of four vms. Verifies
* that each vm is aware of the other vms' groups.
*/
- public void testGroupsInAllVMs() {
- disconnectFromDS(); // or assertion on # members fails when run-dunit-tests
-
+ @Test
+ public void allMembersShouldSeeGroups() {
// connect all four vms...
for (int i = 0; i < 4; i++) {
final int vm = i;
Host.getHost(0).getVM(vm).invoke(new SerializableRunnable() {
public void run() {
- //disconnectFromDS();
- Properties config = new Properties();
+ final Properties config = createConfig();
config.setProperty(DistributionConfig.GROUPS_NAME, makeGroupsString(vm));
getSystem(config);
}
@@ -285,7 +297,7 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
assertEquals(3, members.size());
break;
}
- catch (AssertionFailedError e) {
+ catch (AssertionError e) {
if (i < 3) {
sleep(200);
} else {
@@ -300,8 +312,8 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
others.removeAll(dm.getOtherNormalDistributionManagerIds());
assertEquals(1, others.size());
// test getGroupMembers
- HashSet<DistributedMember> evens = new HashSet<DistributedMember>();
- HashSet<DistributedMember> odds = new HashSet<DistributedMember>();
+ Set<DistributedMember> evens = new HashSet<DistributedMember>();
+ Set<DistributedMember> odds = new HashSet<DistributedMember>();
boolean isEvens = true;
for (String groupName: Arrays.asList("0", "1", "2", "3")) {
Set<DistributedMember> gm = sys.getGroupMembers(groupName);
@@ -337,74 +349,99 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
* Changing the id can result in bad keys in JMX and can result in numerous
* errors in Admin/JMX tests.
*/
- public void testGetId() {
- Properties config = new Properties();
- config.setProperty(DistributionConfig.MCAST_PORT_NAME, "0");
- config.setProperty(DistributionConfig.LOCATORS_NAME, "");
- config.setProperty(DistributionConfig.NAME_NAME, "foobar");
+ @Test
+ public void getIdShouldIdentifyMember() {
+ this.config.setProperty(DistributionConfig.LOCATORS_NAME, "");
+ this.config.setProperty(DistributionConfig.NAME_NAME, "foobar");
- InternalDistributedSystem system = getSystem(config);
- try {
-
- DM dm = system.getDistributionManager();
- DistributedMember member = dm.getDistributionManagerId();
-
- assertEquals(member.getId(), system.getMemberId());
- assertTrue(member.getId().contains("foobar"));
- }
- finally {
- system.disconnect();
- }
+ final InternalDistributedSystem system = getSystem(this.config);
+ final DistributedMember member = system.getDistributedMember();
+
+ assertThat(system.getMemberId(), is(member.getId()));
+ assertThat(member.getId(), containsString("foobar"));
}
- public void testFindMemberByName() {
- disconnectAllFromDS(); // or assertion on # members fails when run-dunit-tests
- VM vm0 = Host.getHost(0).getVM(0);
- VM vm1 = Host.getHost(0).getVM(1);
- VM vm2 = Host.getHost(0).getVM(2);
+ /**
+ * TODO: move to DistributedSystem DUnit Test
+ */
+ @Test
+ public void findDistributedMembersByNameShouldReturnOneMember() {
+ final VM vm0 = Host.getHost(0).getVM(0);
+ final VM vm1 = Host.getHost(0).getVM(1);
+ final VM vm2 = Host.getHost(0).getVM(2);
+
final DistributedMember member0 = createSystemAndGetId(vm0, "name0");
final DistributedMember member1 = createSystemAndGetId(vm1, "name1");
final DistributedMember member2 = createSystemAndGetId(vm2, "name2");
- vm0.invoke(new SerializableRunnable() {
- public void run() {
+
+ vm0.invoke(new SerializableCallable() { // SerializableRunnable
+ public Object call() throws Exception { // public void run()
DistributedSystem system = getSystem();
assertEquals(member0, system.findDistributedMember("name0"));
assertEquals(member1, system.findDistributedMember("name1"));
assertEquals(member2, system.findDistributedMember("name2"));
assertNull(system.findDistributedMember("name3"));
- Set<DistributedMember> members;
- try {
- members = system.findDistributedMembers(InetAddress.getByName(member0.getHost()));
- HashSet expected = new HashSet();
- expected.add(member0);
- expected.add(member1);
- expected.add(member2);
-
- //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);
- }
+ Set<DistributedMember> members = system.findDistributedMembers(InetAddress.getByName(member0.getHost()));
+ Set<DistributedMember> expected = new HashSet<DistributedMember>();
+ expected.add(member0);
+ expected.add(member1);
+ expected.add(member2);
+
+ // 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;
}
});
}
- private DistributedMember createSystemAndGetId(VM vm, final String name) {
+ @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
public Object call() throws Exception {
- Properties config = new Properties();
+ final Properties config = createConfig();
config.setProperty(DistributionConfig.NAME_NAME, name);
- DistributedSystem ds = getSystem(config);
+ final DistributedSystem ds = getSystem(config);
return ds.getDistributedMember();
}
});
}
+
+ private static Properties createConfig() {
+ final Properties props = new Properties();
+ props.setProperty(DistributionConfig.MCAST_PORT_NAME, "0");
+ return props;
+ }
-}
+ private void sleep(final long millis) {
+ try {
+ Thread.sleep(millis);
+ } catch (InterruptedException e) {
+ fail("interrupted");
+ }
+ }
-
+ private static String makeOddEvenString(final int vm) {
+ return ((vm % 2) == 0) ? "EVENS" : "ODDS";
+ }
+
+ private static String makeGroupsString(final int vm) {
+ return "" + vm + ", " + makeOddEvenString(vm);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/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 a0e54d5..e74e12f 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
@@ -1,5 +1,10 @@
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;
import java.util.Collection;
import java.util.HashSet;
@@ -7,6 +12,14 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
+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;
import com.gemstone.gemfire.distributed.LocatorLauncher.LocatorState;
@@ -18,10 +31,13 @@ import com.gemstone.gemfire.internal.AvailablePortHelper;
import com.gemstone.gemfire.internal.SocketCreator;
import com.gemstone.gemfire.internal.util.StopWatch;
-import dunit.DistributedTestCase;
-import dunit.Host;
-import dunit.SerializableCallable;
-import dunit.SerializableRunnable;
+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.junit.categories.DistributedTest;
+import com.gemstone.gemfire.test.junit.categories.MembershipTest;
+import com.gemstone.gemfire.test.junit.rules.Retry;
/**
* Extracted from LocatorLauncherLocalJUnitTest.
@@ -29,26 +45,36 @@ import dunit.SerializableRunnable;
* @author Kirk Lund
* @since 8.0
*/
+@SuppressWarnings("serial")
+@Category({ DistributedTest.class, MembershipTest.class })
public class HostedLocatorsDUnitTest extends DistributedTestCase {
- protected static final int TIMEOUT_MILLISECONDS = 5 * 60 * 1000; // 5 minutes
+ //protected static final int TIMEOUT_MILLISECONDS = 5 * 60 * 1000; // 5 minutes
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 Retry retry = new Retry(2);
+
+ @Before
public void setUp() throws Exception {
disconnectAllFromDS();
}
- public void tearDown2() throws Exception {
+ @After
+ public void tearDown() throws Exception {
disconnectAllFromDS();
}
- public HostedLocatorsDUnitTest(String name) {
- super(name);
- }
-
- public void testGetAllHostedLocators() throws Exception {
+ @Test
+ public void getAllHostedLocators() throws Exception {
final InternalDistributedSystem system = getSystem();
final String dunitLocator = system.getConfig().getLocators();
assertNotNull(dunitLocator);
@@ -79,7 +105,8 @@ public class HostedLocatorsDUnitTest extends DistributedTestCase {
launcher = builder.build();
assertEquals(Status.ONLINE, launcher.start().getStatus());
- waitForLocatorToStart(launcher, TIMEOUT_MILLISECONDS, 10, true);
+ //was: waitForLocatorToStart(launcher, TIMEOUT_MILLISECONDS, 10, true);
+ with().pollInterval(10, MILLISECONDS).await().atMost(5, MINUTES).until( isLocatorStarted() );
return null;
} finally {
System.clearProperty("gemfire.locators");
@@ -154,6 +181,23 @@ 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 {
+ final LocatorState LocatorState = launcher.status();
+ return (LocatorState != null && Status.ONLINE.equals(LocatorState.getStatus()));
+ }
+ };
+ }
+
protected void waitForLocatorToStart(final LocatorLauncher launcher, int timeout, int interval, boolean throwOnTimeout) throws Exception {
assertEventuallyTrue("waiting for process to start: " + launcher.status(), new Callable<Boolean>() {
@Override
@@ -176,4 +220,6 @@ public class HostedLocatorsDUnitTest extends DistributedTestCase {
}
assertTrue(message, done);
}
+
+ private static int count = 0;
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/MembershipTestSuite.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/MembershipTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/MembershipTestSuite.java
new file mode 100755
index 0000000..c96bf43
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/MembershipTestSuite.java
@@ -0,0 +1,17 @@
+package com.gemstone.gemfire.distributed;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ DistributedMemberDUnitTest.class,
+ HostedLocatorsDUnitTest.class,
+})
+/**
+ * Suite of tests for Membership.
+ *
+ * @author Kirk Lund
+ */
+public class MembershipTestSuite {
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java
index a7921ee..644d82c 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java
@@ -1,16 +1,23 @@
package com.gemstone.gemfire.internal.offheap;
+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 static org.junit.Assert.*;
+
import java.util.Properties;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.logging.log4j.Logger;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
import com.gemstone.gemfire.OutOfOffHeapMemoryException;
import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionShortcut;
-import com.gemstone.gemfire.cache30.CacheTestCase;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.DistributedSystemDisconnectedException;
import com.gemstone.gemfire.distributed.internal.DistributionConfig;
@@ -21,49 +28,33 @@ import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
import com.gemstone.gemfire.internal.cache.OffHeapTestUtil;
import com.gemstone.gemfire.internal.logging.LogService;
import com.gemstone.gemfire.internal.util.StopWatch;
+import com.gemstone.gemfire.test.dunit.cache.CacheTestCase;
+import com.gemstone.gemfire.test.junit.categories.DistributedTest;
-import dunit.Host;
-import dunit.SerializableRunnable;
+import com.gemstone.gemfire.test.dunit.Host;
+import com.gemstone.gemfire.test.dunit.SerializableRunnable;
+import com.gemstone.gemfire.test.dunit.WaitCriterion;
/**
* Test behavior of region when running out of off-heap memory.
*
* @author Kirk Lund
*/
-@SuppressWarnings("serial")
+@SuppressWarnings({ "serial", "unused" })
+@Category(DistributedTest.class)
public class OutOfOffHeapMemoryDUnitTest extends CacheTestCase {
private static final Logger logger = LogService.getLogger();
protected static final AtomicReference<Cache> cache = new AtomicReference<Cache>();
protected static final AtomicReference<DistributedSystem> system = new AtomicReference<DistributedSystem>();
protected static final AtomicBoolean isSmallerVM = new AtomicBoolean();
-
- public OutOfOffHeapMemoryDUnitTest(String name) {
- super(name);
- }
- @Override
- public void setUp() throws Exception {
+ @Before
+ public void setUpOutOfOffHeapMemoryDUnitTest() throws Exception {
disconnectAllFromDS();
- super.setUp();
- addExpectedException(OutOfOffHeapMemoryException.class.getSimpleName());
+ addExpectedExceptionString(OutOfOffHeapMemoryException.class.getSimpleName());
}
-// public static void caseSetUp() {
-// //disconnectAllFromDS();
-// for (int i = 0; i < Host.getHost(0).getVMCount(); i++) {
-// Host.getHost(0).getVM(i).invoke(new SerializableRunnable() {
-// public void run() {
-// InternalDistributedSystem ids = InternalDistributedSystem.getAnyInstance();
-// if (ids != null && ids.isConnected()) {
-// logger.warn(OutOfOffHeapMemoryDUnitTest.class.getSimpleName() + " found DistributedSystem connection from previous test: {}", ids);
-// ids.disconnect();
-// }
-// }
-// });
-// }
-// }
-
@Override
public void tearDown2() throws Exception {
final SerializableRunnable checkOrphans = new SerializableRunnable() {
@@ -83,7 +74,6 @@ public class OutOfOffHeapMemoryDUnitTest extends CacheTestCase {
}
}
- @SuppressWarnings("unused") // invoked by reflection from tearDown2()
private static void cleanup() {
disconnectFromDS();
SimpleMemoryAllocatorImpl.freeOffHeapMemory();
@@ -121,6 +111,7 @@ public class OutOfOffHeapMemoryDUnitTest extends CacheTestCase {
return props;
}
+ @Test
public void testSimpleOutOfOffHeapMemoryMemberDisconnects() {
final DistributedSystem system = getSystem();
final Cache cache = getCache();
@@ -209,6 +200,7 @@ public class OutOfOffHeapMemoryDUnitTest extends CacheTestCase {
}
}
+ @Test
public void testOtherMembersSeeOutOfOffHeapMemoryMemberDisconnects() {
final int vmCount = Host.getHost(0).getVMCount();
assertEquals(4, vmCount);
@@ -301,44 +293,4 @@ public class OutOfOffHeapMemoryDUnitTest extends CacheTestCase {
});
}
}
-
-// private static void foo() {
-// final WaitCriterion waitForDisconnect = new WaitCriterion() {
-// public boolean done() {
-// return cache.isClosed() && !system.isConnected() && dm.isClosed();
-// }
-// public String description() {
-// return "Waiting for cache, system and dm to close";
-// }
-// };
-// waitForCriterion(waitForDisconnect, 10*1000, 100, true);
-// }
-
- // setUp() and caseSetUp() are commented out -- they were in place because of incompatible DistributedSystem bleed over from earlier DUnit tests
-
-//@Override
-//public void setUp() throws Exception {
-// super.setUp();
-// long begin = System.currentTimeMillis();
-// Cache gfc = null;
-// while (gfc == null) {
-// try {
-// gfc = getCache();
-// break;
-// } catch (IllegalStateException e) {
-// if (System.currentTimeMillis() > begin+60*1000) {
-// fail("OutOfOffHeapMemoryDUnitTest waited too long to getCache", e);
-// } else if (e.getMessage().contains("A connection to a distributed system already exists in this VM. It has the following configuration")) {
-// InternalDistributedSystem ids = InternalDistributedSystem.getAnyInstance();
-// if (ids != null && ids.isConnected()) {
-// ids.getLogWriter().warning("OutOfOffHeapMemoryDUnitTest found DistributedSystem connection from previous test", e);
-// ids.disconnect();
-// }
-// } else {
-// throw e;
-// }
-// }
-// }
-//}
-
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionDUnitTest.java
new file mode 100755
index 0000000..a3fc1f1
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionDUnitTest.java
@@ -0,0 +1,63 @@
+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 static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+import org.junit.Test;
+
+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.SerializableCallable;
+import com.gemstone.gemfire.test.dunit.VM;
+
+/**
+ * Using Catch-Exception works well for remote exceptions and asserting details
+ * about root cause of RMIExceptions in DUnit tests.
+ */
+public class CatchExceptionDUnitTest extends DistributedTestCase {
+ private static final long serialVersionUID = 1L;
+
+ private static final String REMOTE_THROW_EXCEPTION_MESSAGE = "Throwing remoteThrowException";
+
+ @Test
+ public void testRemoteInvocationWithException() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+
+ when(vm).invoke(new ThrowBasicTestException());
+
+ then(caughtException())
+ .isInstanceOf(RMIException.class)
+ .hasCause(new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE));
+ }
+
+ protected static class ThrowBasicTestException extends SerializableCallable<Object> {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public Object call() throws Exception {
+ throw new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE);
+ }
+ }
+
+ 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/catchexception/CatchExceptionJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionJUnitTest.java
new file mode 100755
index 0000000..d197745
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionJUnitTest.java
@@ -0,0 +1,95 @@
+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;
+
+/**
+ * Simple unit tests exercising Catch-Exception with AssertJ, Hamcrest and JUnit.
+ */
+public class CatchExceptionJUnitTest {
+
+ @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/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Assert.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Assert.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Assert.java
new file mode 100755
index 0000000..a8ce347
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Assert.java
@@ -0,0 +1,11 @@
+package com.gemstone.gemfire.test.dunit;
+
+/**
+ * Extracted from DistributedTestCase
+ */
+public class Assert extends org.junit.Assert {
+
+ public static void fail(final String message, final Throwable cause) {
+ throw new AssertionError(cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/AsyncInvocation.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/AsyncInvocation.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/AsyncInvocation.java
new file mode 100644
index 0000000..0fdcd74
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/AsyncInvocation.java
@@ -0,0 +1,206 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import java.util.concurrent.TimeoutException;
+
+import com.gemstone.gemfire.InternalGemFireError;
+import com.gemstone.gemfire.SystemFailure;
+
+// @todo davidw Add the ability to get a return value back from the
+// async method call. (Use a static ThreadLocal field that is
+// accessible from the Runnable used in VM#invoke)
+/**
+ * <P>An <code>AsyncInvocation</code> represents the invocation of a
+ * remote invocation that executes asynchronously from its caller. An
+ * instanceof <code>AsyncInvocation</code> provides information about
+ * the invocation such as any exception that it may have thrown.</P>
+ *
+ * <P>Because it is a <code>Thread</code>, an
+ * <code>AsyncInvocation</code> can be used as follows:</P>
+ *
+ * <PRE>
+ * AsyncInvocation ai1 = vm.invokeAsync(Test.class, "method1");
+ * AsyncInvocation ai2 = vm.invokeAsync(Test.class, "method2");
+ *
+ * ai1.join();
+ * ai2.join();
+ *
+ * assertTrue("Exception occurred while invoking " + ai1,
+ * !ai1.exceptionOccurred());
+ * if (ai2.exceptionOccurred()) {
+ * throw ai2.getException();
+ * }
+ * </PRE>
+ *
+ * @see VM#invokeAsync(Class, String)
+ */
+public class AsyncInvocation extends Thread {
+
+ private static final ThreadLocal returnValue = new ThreadLocal();
+
+ /** The singleton the thread group */
+ private static final ThreadGroup GROUP = new AsyncInvocationGroup();
+
+ ///////////////////// Instance Fields /////////////////////
+
+ /** An exception thrown while this async invocation ran */
+ protected volatile Throwable exception;
+
+ /** The object (or class) that is the receiver of this asyn method
+ * invocation */
+ private Object receiver;
+
+ /** The name of the method being invoked */
+ private String methodName;
+
+ /** The returned object if any */
+ public volatile Object returnedObj = null;
+
+ ////////////////////// Constructors //////////////////////
+
+ /**
+ * Creates a new <code>AsyncInvocation</code>
+ *
+ * @param receiver
+ * The object or {@link Class} on which the remote method was
+ * invoked
+ * @param methodName
+ * The name of the method being invoked
+ * @param work
+ * The actual invocation of the method
+ */
+ public AsyncInvocation(Object receiver, String methodName, Runnable work) {
+ super(GROUP, work, getName(receiver, methodName));
+ this.receiver = receiver;
+ this.methodName = methodName;
+ this.exception = null;
+ }
+
+ ////////////////////// Static Methods /////////////////////
+
+ /**
+ * Returns the name of a <code>AsyncInvocation</code> based on its
+ * receiver and method name.
+ */
+ private static String getName(Object receiver, String methodName) {
+ StringBuffer sb = new StringBuffer(methodName);
+ sb.append(" invoked on ");
+ if (receiver instanceof Class) {
+ sb.append("class ");
+ sb.append(((Class) receiver).getName());
+
+ } else {
+ sb.append("an instance of ");
+ sb.append(receiver.getClass().getName());
+ }
+
+ return sb.toString();
+ }
+
+ ///////////////////// Instance Methods ////////////////////
+
+ /**
+ * Returns the receiver of this async method invocation
+ */
+ public Object getReceiver() {
+ return this.receiver;
+ }
+
+ /**
+ * Returns the name of the method being invoked remotely
+ */
+ public String getMethodName() {
+ return this.methodName;
+ }
+
+ /**
+ * Returns whether or not an exception occurred during this async
+ * method invocation.
+ */
+ public boolean exceptionOccurred() {
+ if (this.isAlive()) {
+ throw new InternalGemFireError("Exception status not available while thread is alive.");
+ }
+ return this.exception != null;
+ }
+
+ /**
+ * Returns the exception that was thrown during this async method
+ * invocation.
+ */
+ public Throwable getException() {
+ if (this.isAlive()) {
+ throw new InternalGemFireError("Exception status not available while thread is alive.");
+ }
+ if (this.exception instanceof RMIException) {
+ return ((RMIException) this.exception).getCause();
+
+ } else {
+ return this.exception;
+ }
+ }
+
+ ////////////////////// Inner Classes //////////////////////
+
+ /**
+ * A <code>ThreadGroup</code> that notices when an exception occurrs
+ * during an <code>AsyncInvocation</code>.
+ */
+ private static class AsyncInvocationGroup extends ThreadGroup {
+ AsyncInvocationGroup() {
+ super("Async Invocations");
+ }
+
+ public void uncaughtException(Thread t, Throwable e) {
+ if (e instanceof VirtualMachineError) {
+ SystemFailure.setFailure((VirtualMachineError)e); // don't throw
+ }
+ if (t instanceof AsyncInvocation) {
+ ((AsyncInvocation) t).exception = e;
+ }
+ }
+ }
+
+ public Object getResult() throws Throwable {
+ join();
+ if(this.exceptionOccurred()) {
+ throw new Exception("An exception occured during async invocation", this.exception);
+ }
+ return this.returnedObj;
+ }
+
+ public Object getResult(long waitTime) throws Throwable {
+ join(waitTime);
+ if(this.isAlive()) {
+ throw new TimeoutException();
+ }
+ if(this.exceptionOccurred()) {
+ throw new Exception("An exception occured during async invocation", this.exception);
+ }
+ return this.returnedObj;
+ }
+
+ public Object getReturnValue() {
+ if (this.isAlive()) {
+ throw new InternalGemFireError("Return value not available while thread is alive.");
+ }
+ return this.returnedObj;
+ }
+
+ public void run()
+ {
+ super.run();
+ this.returnedObj = returnValue.get();
+ returnValue.set(null);
+ }
+
+ static void setReturnValue(Object v) {
+ returnValue.set(v);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/BounceResult.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/BounceResult.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/BounceResult.java
new file mode 100644
index 0000000..a766a2b
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/BounceResult.java
@@ -0,0 +1,20 @@
+package com.gemstone.gemfire.test.dunit;
+
+public class BounceResult {
+ private final int newPid;
+ private final RemoteDUnitVMIF newClient;
+
+ public BounceResult(int newPid, RemoteDUnitVMIF newClient) {
+ this.newPid = newPid;
+ this.newClient = newClient;
+ }
+
+ public int getNewPid() {
+ return newPid;
+ }
+
+ public RemoteDUnitVMIF getNewClient() {
+ return newClient;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/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
new file mode 100644
index 0000000..96ebd7d
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitEnv.java
@@ -0,0 +1,68 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+/**
+ *
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import java.io.File;
+import java.rmi.RemoteException;
+import java.util.Properties;
+
+/**
+ * This class provides an abstraction over the environment
+ * that is used to run dunit. This will delegate to the hydra
+ * or to the standalone dunit launcher as needed.
+ *
+ * Any dunit tests that rely on hydra configuration should go
+ * through here, so that we can separate them out from depending on hydra
+ * and run them on a different VM launching system.
+ *
+ * @author dsmith
+ *
+ */
+public abstract class DUnitEnv {
+
+ public static DUnitEnv instance = null;
+
+ public static final DUnitEnv get() {
+ if (instance == null) {
+ try {
+ // for tests that are still being migrated to the open-source
+ // distributed unit test framework we need to look for this
+ // old closed-source dunit environment
+ Class clazz = Class.forName("dunit.hydra.HydraDUnitEnv");
+ instance = (DUnitEnv)clazz.newInstance();
+ } catch (Exception e) {
+ throw new Error("Distributed unit test environment is not initialized");
+ }
+ }
+ return instance;
+ }
+
+ public static void set(DUnitEnv dunitEnv) {
+ instance = dunitEnv;
+ }
+
+ public abstract String getLocatorString();
+
+ public abstract String getLocatorAddress();
+
+ public abstract int getLocatorPort();
+
+ public abstract Properties getDistributedSystemProperties();
+
+ public abstract int getPid();
+
+ public abstract int getVMID();
+
+ public abstract BounceResult bounce(int pid) throws RemoteException;
+
+ public abstract File getWorkingDirectory(int pid);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DebuggerSupport.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DebuggerSupport.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DebuggerSupport.java
new file mode 100755
index 0000000..8d57483
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DebuggerSupport.java
@@ -0,0 +1,20 @@
+package com.gemstone.gemfire.test.dunit;
+
+/**
+ * Extracted from DistributedTestCase. Enters infinite loop to allow debugger to attach.
+ */
+public class DebuggerSupport {
+
+ protected DebuggerSupport() {
+ }
+
+ @SuppressWarnings("serial")
+ public static void attachDebugger(VM vm, final String msg) {
+ vm.invoke(new SerializableRunnable("Attach Debugger") {
+ public void run() {
+ com.gemstone.gemfire.internal.util.DebuggerSupport.
+ waitForJavaDebugger(msg);
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedTestCase.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedTestCase.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedTestCase.java
new file mode 100755
index 0000000..5eb3b0b
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedTestCase.java
@@ -0,0 +1,659 @@
+package com.gemstone.gemfire.test.dunit;
+
+import static com.gemstone.gemfire.test.dunit.Invoke.*;
+import static com.gemstone.gemfire.test.dunit.Wait.*;
+import static org.junit.Assert.*;
+
+import java.io.File;
+import java.net.UnknownHostException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.logging.log4j.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+
+import com.gemstone.gemfire.admin.internal.AdminDistributedSystemImpl;
+import com.gemstone.gemfire.cache.hdfs.internal.hoplog.HoplogConfig;
+import com.gemstone.gemfire.cache.query.QueryTestUtils;
+import com.gemstone.gemfire.cache.query.internal.QueryObserverHolder;
+import com.gemstone.gemfire.cache30.GlobalLockingDUnitTest;
+import com.gemstone.gemfire.cache30.MultiVMRegionTestCase;
+import com.gemstone.gemfire.cache30.RegionTestCase;
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.distributed.internal.DistributionMessageObserver;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem.CreationStackGenerator;
+import com.gemstone.gemfire.distributed.internal.membership.jgroup.MembershipManagerHelper;
+import com.gemstone.gemfire.internal.AvailablePort;
+import com.gemstone.gemfire.internal.InternalDataSerializer;
+import com.gemstone.gemfire.internal.InternalInstantiator;
+import com.gemstone.gemfire.internal.SocketCreator;
+import com.gemstone.gemfire.internal.admin.ClientStatsManager;
+import com.gemstone.gemfire.internal.cache.GemFireCacheImpl;
+import com.gemstone.gemfire.internal.cache.InitialImageOperation;
+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.ManagerLogWriter;
+import com.gemstone.gemfire.internal.logging.log4j.LogWriterLogger;
+import com.gemstone.gemfire.management.internal.cli.LogWrapper;
+import com.gemstone.org.jgroups.Event;
+import com.gemstone.org.jgroups.JChannel;
+import com.gemstone.org.jgroups.stack.IpAddress;
+import com.gemstone.org.jgroups.stack.Protocol;
+import com.gemstone.org.jgroups.util.GemFireTracer;
+
+import com.gemstone.gemfire.test.dunit.standalone.DUnitLauncher;
+
+/**
+ * This class is the superclass of all distributed unit tests.
+ *
+ * @author David Whitlock
+ */
+@SuppressWarnings({ "deprecation", "serial", "rawtypes" })
+public abstract class DistributedTestCase implements java.io.Serializable {
+ private static final Logger logger = LogService.getLogger();
+ private static final LogWriterLogger oldLogger = LogWriterLogger.create(logger);
+
+ @Rule
+ public transient TestName testNameRule = new TestName();
+
+ public static InternalDistributedSystem system;
+ private static Class lastSystemCreatedInTest;
+ private static Properties lastSystemProperties;
+ public static volatile String testName;
+
+ public static final boolean logPerTest = Boolean.getBoolean("dunitLogPerTest");
+
+ /**
+ * Creates a new <code>DistributedTestCase</code> test.
+ */
+ public DistributedTestCase() {
+ DUnitLauncher.launchIfNeeded();
+ }
+
+ 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");
+ }
+ 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 Class getTestClass() {
+ Class clazz = getClass();
+ while (clazz.getDeclaringClass() != null) {
+ clazz = clazz.getDeclaringClass();
+ }
+ return clazz;
+ }
+
+ /**
+ * This finds the log level configured for the test run. It should be used
+ * when creating a new distributed system if you want to specify a log level.
+ *
+ * @return the dunit log-level setting
+ */
+ public static String getDUnitLogLevel() { // TODO: delete
+ Properties p = DUnitEnv.get().getDistributedSystemProperties();
+ String result = p.getProperty(DistributionConfig.LOG_LEVEL_NAME);
+ if (result == null) {
+ result = ManagerLogWriter.levelToString(DistributionConfig.DEFAULT_LOG_LEVEL);
+ }
+ return result;
+ }
+
+ public final static Properties getAllDistributedSystemProperties(Properties props) { // TODO: delete
+ Properties p = DUnitEnv.get().getDistributedSystemProperties();
+
+ // our tests do not expect auto-reconnect to be on by default
+ if (!p.contains(DistributionConfig.DISABLE_AUTO_RECONNECT_NAME)) {
+ p.put(DistributionConfig.DISABLE_AUTO_RECONNECT_NAME, "true");
+ }
+
+ for (Iterator iter = props.entrySet().iterator();
+ iter.hasNext(); ) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String key = (String) entry.getKey();
+ Object value = entry.getValue();
+ p.put(key, value);
+ }
+ return p;
+ }
+
+ public void setSystem(Properties props, DistributedSystem ds) { // TODO: delete
+ system = (InternalDistributedSystem)ds;
+ lastSystemProperties = props;
+ lastSystemCreatedInTest = getTestClass();
+ }
+
+ /**
+ * 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 props) {
+ // Setting the default disk store name is now done in setUp
+ if (system == null) {
+ system = InternalDistributedSystem.getAnyInstance();
+ }
+ if (system == null || !system.isConnected()) {
+ // Figure out our distributed system properties
+ Properties p = getAllDistributedSystemProperties(props);
+ lastSystemCreatedInTest = getTestClass();
+ if (logPerTest) {
+ String testMethod = getTestName();
+ String testName = lastSystemCreatedInTest.getName() + '-' + testMethod;
+ String oldLogFile = p.getProperty(DistributionConfig.LOG_FILE_NAME);
+ p.put(DistributionConfig.LOG_FILE_NAME,
+ oldLogFile.replace("system.log", testName+".log"));
+ String oldStatFile = p.getProperty(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME);
+ p.put(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME,
+ oldStatFile.replace("statArchive.gfs", testName+".gfs"));
+ }
+ system = (InternalDistributedSystem)DistributedSystem.connect(p);
+ lastSystemProperties = p;
+ } else {
+ boolean needNewSystem = false;
+ if(!getTestClass().equals(lastSystemCreatedInTest)) {
+ Properties newProps = getAllDistributedSystemProperties(props);
+ needNewSystem = !newProps.equals(lastSystemProperties);
+ if(needNewSystem) {
+ getLogWriter().info(
+ "Test class has changed and the new DS properties are not an exact match. "
+ + "Forcing DS disconnect. Old props = "
+ + lastSystemProperties + "new props=" + newProps);
+ }
+ } else {
+ Properties activeProps = system.getProperties();
+ for (Iterator iter = props.entrySet().iterator();
+ iter.hasNext(); ) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String key = (String) entry.getKey();
+ String value = (String) entry.getValue();
+ if (!value.equals(activeProps.getProperty(key))) {
+ needNewSystem = true;
+ getLogWriter().info("Forcing DS disconnect. For property " + key
+ + " old value = " + activeProps.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.
+ getLogWriter().info("Disconnecting from current DS in order to make a new one");
+ disconnectFromDS();
+ getSystem(props);
+ }
+ }
+ return system;
+ }
+
+ /**
+ * Crash the cache in the given VM in such a way that it immediately stops communicating with
+ * peers. This forces the VM's membership manager to throw a ForcedDisconnectException by
+ * forcibly terminating the JGroups protocol stack with a fake EXIT event.<p>
+ *
+ * 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 static boolean crashDistributedSystem(VM vm) { // TODO: move
+ return (Boolean)vm.invoke(new SerializableCallable("crash distributed system") {
+ public Object call() throws Exception {
+ DistributedSystem msys = InternalDistributedSystem.getAnyInstance();
+ crashDistributedSystem(msys);
+ return true;
+ }
+ });
+ }
+
+ /**
+ * Crash the cache in the given VM in such a way that it immediately stops communicating with
+ * peers. This forces the VM's membership manager to throw a ForcedDisconnectException by
+ * forcibly terminating the JGroups protocol stack with a fake EXIT event.<p>
+ *
+ * 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 static void crashDistributedSystem(final DistributedSystem msys) { // TODO: move
+ MembershipManagerHelper.inhibitForcedDisconnectLogging(true);
+ MembershipManagerHelper.playDead(msys);
+ JChannel c = MembershipManagerHelper.getJChannel(msys);
+ Protocol udp = c.getProtocolStack().findProtocol("UDP");
+ udp.stop();
+ udp.passUp(new Event(Event.EXIT, new RuntimeException("killing member's ds")));
+ try {
+ MembershipManagerHelper.getJChannel(msys).waitForClose();
+ }
+ catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ // attempt rest of work with interrupt bit set
+ }
+ MembershipManagerHelper.inhibitForcedDisconnectLogging(false);
+ WaitCriterion wc = new WaitCriterion() {
+ public boolean done() {
+ return !msys.isConnected();
+ }
+ public String description() {
+ return "waiting for distributed system to finish disconnecting: " + msys;
+ }
+ };
+// try {
+ waitForCriterion(wc, 10000, 1000, true);
+// } finally {
+// dumpMyThreads(getLogWriter());
+// }
+ }
+
+ private String getDefaultDiskStoreName() { // TODO: move
+ String vmid = System.getProperty("vmid");
+ return "DiskStore-" + vmid + "-"+ getTestClass().getCanonicalName() + "." + getTestName();
+ }
+
+ /**
+ * 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());
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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);
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * 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();
+ }
+
+ /**
+ * Sets up the test (noop).
+ */
+ @Before
+ public final void setUpDistributedTestCase() throws Exception {
+ setUpCreationStackGenerator();
+ testName = getName();
+ System.setProperty(HoplogConfig.ALLOW_LOCAL_HDFS_PROP, "true");
+
+ if (testName != null) {
+ GemFireCacheImpl.setDefaultDiskStoreName(getDefaultDiskStoreName());
+ String baseDefaultDiskStoreName = getTestClass().getCanonicalName() + "." + getTestName();
+ 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);
+ String vmDefaultDiskStoreName = "DiskStore-" + h + "-" + v + "-" + baseDefaultDiskStoreName;
+ vm.invoke(DistributedTestCase.class, "perVMSetUp", new Object[] {testName, vmDefaultDiskStoreName});
+ }
+ }
+ }
+ System.out.println("\n\n[setup] START TEST " + getClass().getSimpleName()+"."+testName+"\n\n");
+ }
+
+ public static void perVMSetUp(String name, String defaultDiskStoreName) { // TODO: move
+ setTestName(name);
+ GemFireCacheImpl.setDefaultDiskStoreName(defaultDiskStoreName);
+ System.setProperty(HoplogConfig.ALLOW_LOCAL_HDFS_PROP, "true");
+ }
+
+ public static void setTestName(String name) {
+ testName = name;
+ }
+
+ public static String getTestName() {
+ return testName;
+ }
+
+ /**
+ * 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 #tearDown2()} instead.
+ * @throws Exception
+ */
+ @After
+ public final void tearDownDistributedTestCase() throws Exception {
+ tearDownCreationStackGenerator();
+ tearDown2();
+ realTearDown();
+ tearDownAfter();
+ }
+
+ /**
+ * 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()
+ */
+ // TODO rename this method to tearDownBefore and change the access modifier to protected!
+ public void tearDown2() throws Exception { // TODO: rename
+ }
+
+ protected void realTearDown() throws Exception {
+ if (logPerTest) {
+ disconnectFromDS();
+ invokeInEveryVM(DistributedTestCase.class, "disconnectFromDS");
+ }
+ cleanupAllVms();
+ }
+
+ /**
+ * 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 #tearDown2()
+ */
+ protected void tearDownAfter() throws Exception {
+ }
+
+ public static void cleanupAllVms()
+ {
+ cleanupThisVM();
+ invokeInEveryVM(DistributedTestCase.class, "cleanupThisVM");
+ invokeInLocator(new SerializableRunnable() {
+ public void run() {
+ DistributionMessageObserver.setInstance(null);
+ unregisterInstantiatorsInThisVM();
+ }
+ });
+ DUnitLauncher.closeAndCheckForSuspects();
+ }
+
+
+ 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() // TODO: move
+ {
+ unregisterDataSerializerInThisVM();
+ invokeInEveryVM(new SerializableRunnable() {
+ public void run() {
+ unregisterDataSerializerInThisVM();
+ }
+ });
+ invokeInLocator(new SerializableRunnable() {
+ public void run() {
+ unregisterDataSerializerInThisVM();
+ }
+ });
+ }
+
+ public static void unregisterInstantiatorsInThisVM() { // TODO: move
+ // unregister all the instantiators
+ InternalInstantiator.reinitialize();
+ assertEquals(0, InternalInstantiator.getInstantiators().length);
+ }
+
+ public static void unregisterDataSerializerInThisVM() // TODO: move
+ {
+ 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");
+ }
+
+ /**
+ * Disconnects this VM from the distributed system
+ */
+ public static void disconnectFromDS() {
+ testName = null;
+ 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();
+ }
+ }
+ }
+
+ /**
+ * Strip the package off and gives just the class name.
+ * Needed because of Windows file name limits.
+ */
+ private String getShortClassName() {
+ String result = this.getClass().getName();
+ int idx = result.lastIndexOf('.');
+ if (idx != -1) {
+ result = result.substring(idx+1);
+ }
+ return result;
+ }
+
+ /** get the host name to use for a server cache in client/server dunit
+ * testing
+ * @param host
+ * @return the host name
+ */
+ public static String getServerHostName(Host host) { // TODO: move
+ return System.getProperty("gemfire.server-bind-address") != null?
+ System.getProperty("gemfire.server-bind-address")
+ : host.getHostName();
+ }
+
+ /** get the IP literal name for the current host, use this instead of
+ * "localhost" to avoid IPv6 name resolution bugs in the JDK/machine config.
+ * @return an ip literal, this method honors java.net.preferIPvAddresses
+ */
+ public static String getIPLiteral() { // TODO: move
+ try {
+ return SocketCreator.getLocalHost().getHostAddress();
+ } catch (UnknownHostException e) {
+ throw new Error("problem determining host IP address", e);
+ }
+ }
+
+
+ /**
+ * Get the port that the standard dunit locator is listening on.
+ * @return
+ */
+ public static int getDUnitLocatorPort() { // TODO: move
+ return DUnitEnv.get().getLocatorPort();
+ }
+
+ public String getName() {
+ return this.testNameRule.getMethodName();
+ }
+
+ /**
+ * 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 String getUniqueName() {
+ return getClass().getSimpleName() + "_" + getName();
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Delete locator state files. Use this after getting a random port
+ * to ensure that an old locator state file isn't picked up by the
+ * new locator you're starting.
+ *
+ * @param ports
+ */
+ public static void deleteLocatorStateFile(final int... ports) { // TODO: move
+ for (int i=0; i<ports.length; i++) {
+ final File stateFile = new File("locator"+ports[i]+"state.dat");
+ if (stateFile.exists()) {
+ stateFile.delete();
+ }
+ }
+ }
+
+}
[7/9] incubator-geode git commit: Test framework refactoring
Posted by kl...@apache.org.
Test framework refactoring
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/33d2c1c8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/33d2c1c8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/33d2c1c8
Branch: refs/heads/feature/GEODE-217
Commit: 33d2c1c86e0532f1b913f6728be85fdd2cf68782
Parents: fcd2142
Author: Kirk Lund <kl...@pivotal.io>
Authored: Fri Aug 21 13:17:45 2015 -0700
Committer: Kirk Lund <kl...@pivotal.io>
Committed: Fri Aug 21 13:17:45 2015 -0700
----------------------------------------------------------------------
.../internal/lang/reflect/ReflectionUtils.java | 41 +++++
.../lang/reflect/ReflectionUtilsJUnitTest.java | 78 +++++++++
.../test/dunit/DistributedSystemSupport.java | 102 ++++++++++++
.../gemfire/test/dunit/NetworkSupport.java | 23 +++
.../test/dunit/tests/DUnitTestSuite.java | 16 ++
.../tests/DistributedTestNameDUnitTest.java | 75 +++++++++
.../gemfire/test/dunit/tests/MyTestSuite.java | 23 +++
.../gemfire/test/golden/GoldenTestSuite.java | 27 ++++
.../com/gemstone/gemfire/test/junit/Retry.java | 17 ++
.../gemfire/test/junit/rules/RetryRule.java | 161 +++++++++++++++++++
10 files changed, 563 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/gemfire-core/src/main/java/com/gemstone/gemfire/internal/lang/reflect/ReflectionUtils.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/main/java/com/gemstone/gemfire/internal/lang/reflect/ReflectionUtils.java b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/lang/reflect/ReflectionUtils.java
new file mode 100755
index 0000000..0b5fee2
--- /dev/null
+++ b/gemfire-core/src/main/java/com/gemstone/gemfire/internal/lang/reflect/ReflectionUtils.java
@@ -0,0 +1,41 @@
+package com.gemstone.gemfire.internal.lang.reflect;
+
+/**
+ * Utility class for helping in various reflection operations. See the
+ * java.lang.reflect package for the classes that this class utilizes.
+ *
+ * TODO: centralize methods from these classes to here:
+ * <li>com.gemstone.gemfire.management.internal.cli.util.spring.ReflectionUtils
+ * <li>com.gemstone.gemfire.internal.logging.LogService
+ * <li>com.gemstone.gemfire.internal.tools.gfsh.app.misc.util.ReflectionUtil
+ *
+ * @author Kirk Lund
+ * @see com.gemstone.gemfire.internal.tools.gfsh.app.misc.util.ReflectionUtil
+ * @see com.gemstone.gemfire.internal.logging.LogService
+ * @see com.gemstone.gemfire.management.internal.cli.util.spring.ReflectionUtils
+ */
+public abstract class ReflectionUtils {
+
+ /**
+ * Gets the class name of the caller in the current stack at the given {@code depth}.
+ *
+ * @param depth a 0-based index in the current stack.
+ * @return a class name
+ */
+ public static String getClassName(final int depth) {
+ return Thread.currentThread().getStackTrace()[depth].getClassName();
+ }
+
+ public static String getClassName() {
+ return Thread.currentThread().getStackTrace()[2].getClassName();
+ }
+
+ public static String getMethodName(final int depth) {
+ return Thread.currentThread().getStackTrace()[depth].getMethodName();
+ }
+
+ public static String getMethodName() {
+ return Thread.currentThread().getStackTrace()[2].getMethodName();
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/gemfire-core/src/test/java/com/gemstone/gemfire/internal/lang/reflect/ReflectionUtilsJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/lang/reflect/ReflectionUtilsJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/lang/reflect/ReflectionUtilsJUnitTest.java
new file mode 100755
index 0000000..346dc75
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/lang/reflect/ReflectionUtilsJUnitTest.java
@@ -0,0 +1,78 @@
+package com.gemstone.gemfire.internal.lang.reflect;
+
+import static com.gemstone.gemfire.internal.lang.reflect.ReflectionUtils.*;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+/**
+ * Unit tests for the ReflectionUtils class.
+ *
+ * @author Kirk Lund
+ */
+@Category(UnitTest.class)
+public class ReflectionUtilsJUnitTest {
+
+ @Rule
+ public TestWatcher watchman = new TestWatcher() {
+ @Override
+ protected void starting(final Description description) {
+ testClassName = description.getClassName();
+ testMethodName = description.getMethodName();
+ }
+ };
+
+ private String testClassName;
+ private String testMethodName;
+
+ @Test
+ public void getClassNameZeroShouldReturnReflectionUtilsClass() {
+ assertThat(getClassName(0), is(Thread.class.getName()));
+ }
+
+ @Test
+ public void getClassNameOneShouldReturnReflectionUtilsClass() {
+ assertThat(getClassName(1), is(ReflectionUtils.class.getName()));
+ }
+
+ @Test
+ public void getClassNameTwoShouldReturnReflectionUtilsClass() {
+ assertThat(getClassName(2), is(getClass().getName()));
+ assertThat(getClassName(2), is(this.testClassName));
+ }
+
+ @Test
+ public void getClassNameShouldReturnReflectionUtilsClass() {
+ assertThat(getClassName(), is(getClass().getName()));
+ assertThat(getClassName(), is(this.testClassName));
+ }
+
+ @Test
+ public void getMethodNameZeroShouldReturnGetStackTrace() {
+ assertThat(getMethodName(0), is("getStackTrace"));
+ }
+
+ @Test
+ public void getMethodNameOneShouldReturnGetMethodName() {
+ assertThat(getMethodName(1), is("getMethodName"));
+ }
+
+ @Test
+ public void getMethodNameTwoShouldReturnThisMethod() {
+ assertThat(getMethodName(2), is("getMethodNameTwoShouldReturnThisMethod"));
+ assertThat(getMethodName(2), is(this.testMethodName));
+ }
+
+ @Test
+ public void getMethodNameShouldReturnThisMethod() {
+ assertThat(getMethodName(), is("getMethodNameShouldReturnThisMethod"));
+ assertThat(getMethodName(), is(this.testMethodName));
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedSystemSupport.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedSystemSupport.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedSystemSupport.java
new file mode 100755
index 0000000..9c52e46
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedSystemSupport.java
@@ -0,0 +1,102 @@
+package com.gemstone.gemfire.test.dunit;
+
+import static com.gemstone.gemfire.test.dunit.Wait.waitForCriterion;
+
+import java.io.File;
+
+import com.gemstone.gemfire.distributed.DistributedSystem;
+import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
+import com.gemstone.gemfire.distributed.internal.membership.jgroup.MembershipManagerHelper;
+import com.gemstone.org.jgroups.Event;
+import com.gemstone.org.jgroups.JChannel;
+import com.gemstone.org.jgroups.stack.Protocol;
+
+public class DistributedSystemSupport {
+
+ protected DistributedSystemSupport() {
+ }
+
+ /**
+ * Crash the cache in the given VM in such a way that it immediately stops communicating with
+ * peers. This forces the VM's membership manager to throw a ForcedDisconnectException by
+ * forcibly terminating the JGroups protocol stack with a fake EXIT event.<p>
+ *
+ * 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 static boolean crashDistributedSystem(VM vm) { // TODO: move
+ return (Boolean)vm.invoke(new SerializableCallable("crash distributed system") {
+ public Object call() throws Exception {
+ DistributedSystem msys = InternalDistributedSystem.getAnyInstance();
+ crashDistributedSystem(msys);
+ return true;
+ }
+ });
+ }
+
+ /**
+ * Crash the cache in the given VM in such a way that it immediately stops communicating with
+ * peers. This forces the VM's membership manager to throw a ForcedDisconnectException by
+ * forcibly terminating the JGroups protocol stack with a fake EXIT event.<p>
+ *
+ * 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 static void crashDistributedSystem(final DistributedSystem msys) { // TODO: move
+ MembershipManagerHelper.inhibitForcedDisconnectLogging(true);
+ MembershipManagerHelper.playDead(msys);
+ JChannel c = MembershipManagerHelper.getJChannel(msys);
+ Protocol udp = c.getProtocolStack().findProtocol("UDP");
+ udp.stop();
+ udp.passUp(new Event(Event.EXIT, new RuntimeException("killing member's ds")));
+ try {
+ MembershipManagerHelper.getJChannel(msys).waitForClose();
+ }
+ catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ // attempt rest of work with interrupt bit set
+ }
+ MembershipManagerHelper.inhibitForcedDisconnectLogging(false);
+ WaitCriterion wc = new WaitCriterion() {
+ public boolean done() {
+ return !msys.isConnected();
+ }
+ public String description() {
+ return "waiting for distributed system to finish disconnecting: " + msys;
+ }
+ };
+// try {
+ waitForCriterion(wc, 10000, 1000, true);
+// } finally {
+// dumpMyThreads(getLogWriter());
+// }
+ }
+
+ /** get the host name to use for a server cache in client/server dunit
+ * testing
+ * @param host
+ * @return the host name
+ */
+ public static String getServerHostName(Host host) {
+ return System.getProperty("gemfire.server-bind-address") != null?
+ System.getProperty("gemfire.server-bind-address")
+ : host.getHostName();
+ }
+
+ /**
+ * Delete locator state files. Use this after getting a random port
+ * to ensure that an old locator state file isn't picked up by the
+ * new locator you're starting.
+ *
+ * @param ports
+ */
+ public static void deleteLocatorStateFile(final int... ports) {
+ for (int i=0; i<ports.length; i++) {
+ final File stateFile = new File("locator"+ports[i]+"state.dat");
+ if (stateFile.exists()) {
+ stateFile.delete();
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/NetworkSupport.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/NetworkSupport.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/NetworkSupport.java
new file mode 100755
index 0000000..f702b4e
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/NetworkSupport.java
@@ -0,0 +1,23 @@
+package com.gemstone.gemfire.test.dunit;
+
+import java.net.UnknownHostException;
+
+import com.gemstone.gemfire.internal.SocketCreator;
+
+public class NetworkSupport {
+
+ protected NetworkSupport() {
+ }
+
+ /** get the IP literal name for the current host, use this instead of
+ * "localhost" to avoid IPv6 name resolution bugs in the JDK/machine config.
+ * @return an ip literal, this method honors java.net.preferIPvAddresses
+ */
+ public static String getIPLiteral() { // TODO: move
+ try {
+ return SocketCreator.getLocalHost().getHostAddress();
+ } catch (UnknownHostException e) {
+ throw new Error("problem determining host IP address", e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestSuite.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestSuite.java
new file mode 100755
index 0000000..3c9fe83
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestSuite.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,
+ DistributedTestNameDUnitTest.class,
+ VMDUnitTest.class,
+})
+/**
+ * Suite of tests for the test.dunit DUnit Test framework.
+ */
+public class DUnitTestSuite {
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DistributedTestNameDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DistributedTestNameDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DistributedTestNameDUnitTest.java
new file mode 100755
index 0000000..d6afc02
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DistributedTestNameDUnitTest.java
@@ -0,0 +1,75 @@
+package com.gemstone.gemfire.test.dunit.tests;
+
+import static com.gemstone.gemfire.test.dunit.Invoke.*;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TestWatcher;
+import org.junit.runner.Description;
+
+import com.gemstone.gemfire.internal.lang.reflect.ReflectionUtils;
+import com.gemstone.gemfire.test.dunit.DistributedTestCase;
+import com.gemstone.gemfire.test.dunit.SerializableRunnable;
+import com.gemstone.gemfire.test.junit.categories.DistributedTest;
+
+/**
+ * Verifies that test name is available and consistent in the controller JVM
+ * and all 4 dunit JVMs.
+ *
+ * @author Kirk Lund
+ */
+@Category(DistributedTest.class)
+public class DistributedTestNameDUnitTest extends DistributedTestCase {
+ private static final long serialVersionUID = 1L;
+
+ // TODO: remove transient and fix bug so test FAILs fast
+
+ @Rule
+ public transient TestWatcher watchman = new TestWatcher() {
+ protected void starting(final Description description) {
+ testClassName = description.getClassName();
+ testMethodName = description.getMethodName();
+ }
+ };
+
+ private String testClassName;
+ private String testMethodName;
+
+ @Test
+ public void testNameShouldBeConsistentInAllJVMs() throws Exception {
+ final String methodName = this.testMethodName;
+
+ // JUnit Rule provides getMethodName in Controller JVM
+ assertThat(getMethodName(), is(methodName));
+
+ // Controller JVM sets testName = getMethodName in itself and all 4 other JVMs
+ assertThat(getTestName(), is(methodName));
+
+ invokeInEveryVM(new SerializableRunnable(getMethodName()) {
+ private static final long serialVersionUID = 1L;
+ @Override
+ public void run() {
+ assertThat(getTestName(), is(methodName));
+ }
+ });
+ }
+
+ @Test
+ public void uniqueNameShouldBeConsistentInAllJVMs() throws Exception {
+ //final String uniqueName = testClassName + "_" + testMethodName;
+ final String uniqueName = getClass().getSimpleName() + "_" + testMethodName;
+
+ assertThat(getUniqueName(), is(uniqueName));
+
+ invokeInEveryVM(new SerializableRunnable(getMethodName()) {
+ private static final long serialVersionUID = 1L;
+ @Override
+ public void run() {
+ assertThat(getUniqueName(), is(uniqueName));
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/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
new file mode 100755
index 0000000..ec90a36
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java
@@ -0,0 +1,23 @@
+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.catchexception.CatchExceptionExampleDUnitTest;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ BasicDUnitTest.class,
+ DistributedTestNameDUnitTest.class,
+ VMDUnitTest.class,
+
+ CatchExceptionExampleDUnitTest.class,
+ DistributedMemberDUnitTest.class,
+ HostedLocatorsDUnitTest.class,
+ OutOfOffHeapMemoryDUnitTest.class,
+})
+public class MyTestSuite {
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/gemfire-core/src/test/java/com/gemstone/gemfire/test/golden/GoldenTestSuite.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/golden/GoldenTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/golden/GoldenTestSuite.java
new file mode 100755
index 0000000..ef2686e
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/golden/GoldenTestSuite.java
@@ -0,0 +1,27 @@
+package com.gemstone.gemfire.test.golden;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ FailWithErrorInOutputJUnitTest.class,
+ FailWithExtraLineInOutputJUnitTest.class,
+ FailWithLineMissingFromEndOfOutputJUnitTest.class,
+ FailWithLineMissingFromMiddleOfOutputJUnitTest.class,
+ FailWithLoggerErrorInOutputJUnitTest.class,
+ FailWithLoggerFatalInOutputJUnitTest.class,
+ FailWithLoggerWarnInOutputJUnitTest.class,
+ FailWithSevereInOutputJUnitTest.class,
+ FailWithTimeoutOfWaitForOutputToMatchJUnitTest.class,
+ FailWithWarningInOutputJUnitTest.class,
+ PassJUnitTest.class,
+ PassWithExpectedErrorJUnitTest.class,
+ PassWithExpectedSevereJUnitTest.class,
+ PassWithExpectedWarningJUnitTest.class,
+})
+/**
+ * Suite of tests for the test.golden Golden Test framework classes.
+ */
+public class GoldenTestSuite {
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Retry.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Retry.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Retry.java
new file mode 100755
index 0000000..af1dc2f
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Retry.java
@@ -0,0 +1,17 @@
+package com.gemstone.gemfire.test.junit;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Java Annotation used to annotate a test suite class test case method in order to
+ * retry it in case of failure up to the specified maximum attempts.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Retry {
+
+ public static int DEFAULT = 1;
+
+ int value() default DEFAULT;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/33d2c1c8/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RetryRule.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RetryRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RetryRule.java
new file mode 100755
index 0000000..0de55ac
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RetryRule.java
@@ -0,0 +1,161 @@
+package com.gemstone.gemfire.test.junit.rules;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+import com.gemstone.gemfire.test.junit.Retry;
+
+/**
+ * JUnit Rule that enables retrying a failed test up to a maximum number of retries.
+ * </p>
+ * RetryRule can be used globally for all tests in a test case by specifying a
+ * retryCount when instantiating it:
+ * <pre>
+ * @Rule
+ * public final RetryRule retryRule = new RetryRule(3);
+ *
+ * @Test
+ * public void shouldBeRetriedUntilPasses() {
+ * ...
+ * }
+ * </pre>
+ * </p>
+ * The above will result in 3 retries for every test in the test case.
+ * </p>
+ * RetryRule can be used locally for specific tests by annotating the test
+ * method with @Rule and specifying a retryCount for that test:
+ * <pre>
+ * @Rule
+ * public final RetryRule retryRule = new RetryRule();
+ *
+ * @Test
+ * @Retry(3)
+ * public void shouldBeRetriedUntilPasses() {
+ * ...
+ * }
+ * </pre>
+ * </p>
+ * This version of RetryRule will retry a test that fails because of any kind
+ * of Throwable.
+ */
+public class RetryRule implements TestRule {
+ /**
+ * Enables printing of failures to System.err even if test passes on a retry
+ */
+ private static final boolean LOG = false;
+
+ private final AbstractRetryRule implementation;
+
+ public RetryRule() {
+ this.implementation = new LocalRetryRule();
+ }
+
+ public RetryRule(final int retryCount) {
+ this.implementation = new GlobalRetryRule(retryCount);
+ }
+
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return this.implementation.apply(base, description);
+ }
+
+ protected abstract class AbstractRetryRule implements TestRule {
+ protected AbstractRetryRule() {
+ }
+ protected void evaluate(final Statement base, final Description description, final int retryCount) throws Throwable {
+ if (retryCount == 0) {
+
+ }
+ Throwable caughtThrowable = null;
+
+ for (int count = 0; count < retryCount; count++) {
+ try {
+ base.evaluate();
+ return;
+ } catch (Throwable t) {
+ caughtThrowable = t;
+ debug(description.getDisplayName() + ": run " + (count + 1) + " failed");
+ }
+ }
+
+ debug(description.getDisplayName() + ": giving up after " + retryCount + " failures");
+ throw caughtThrowable;
+ }
+ private void debug(final String message) {
+ if (LOG) {
+ System.err.println(message);
+ }
+ }
+ }
+
+ /**
+ * Implementation of RetryRule for all test methods in a test case
+ */
+ protected class GlobalRetryRule extends AbstractRetryRule {
+
+ private final int retryCount;
+
+ protected GlobalRetryRule(final int retryCount) {
+ if (retryCount < 1) {
+ throw new IllegalArgumentException("Retry count must be greater than zero");
+ }
+ this.retryCount = retryCount;
+ }
+
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ GlobalRetryRule.this.evaluatePerCase(base, description);
+ }
+ };
+ }
+
+ protected void evaluatePerCase(final Statement base, final Description description) throws Throwable {
+ evaluate(base, description, this.retryCount);
+ }
+ }
+
+ /**
+ * Implementation of RetryRule for test methods annotated with Retry
+ */
+ protected class LocalRetryRule extends AbstractRetryRule {
+
+ protected LocalRetryRule() {
+ }
+
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ LocalRetryRule.this.evaluatePerTest(base, description);
+ }
+ };
+ }
+
+ protected void evaluatePerTest(final Statement base, final Description description) throws Throwable {
+ if (isTest(description)) {
+ Retry retry = description.getAnnotation(Retry.class);
+ int retryCount = getRetryCount(retry);
+ evaluate(base, description, retryCount);
+ }
+ }
+
+ private int getRetryCount(final Retry retry) {
+ int retryCount = Retry.DEFAULT;
+
+ if (retry != null) {
+ retryCount = retry.value();
+ }
+
+ return retryCount;
+ }
+
+ private boolean isTest(final Description description) {
+ return (description.isSuite() || description.isTest());
+ }
+ }
+}
[3/9] incubator-geode git commit: Dunit changes for JUnit 4 syntax.
Refactoring to modernize API.
Posted by kl...@apache.org.
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 {
+}
[8/9] incubator-geode git commit: More examples and rules
Posted by kl...@apache.org.
More examples and 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/d0c03307
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/d0c03307
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/d0c03307
Branch: refs/heads/feature/GEODE-217
Commit: d0c033074b239162ea6d2f5fde7ac8e329402a24
Parents: 33d2c1c
Author: Kirk Lund <kl...@pivotal.io>
Authored: Fri Aug 21 13:27:27 2015 -0700
Committer: Kirk Lund <kl...@pivotal.io>
Committed: Fri Aug 21 13:27:27 2015 -0700
----------------------------------------------------------------------
.../test/assertj/AssertJExampleJUnitTest.java | 119 ++++++++
.../CatchExceptionExampleDUnitTest.java | 59 ++++
.../CatchExceptionExampleJUnitTest.java | 99 +++++++
.../JUnitParamsExampleJUnitTest.java | 36 +++
.../com/gemstone/gemfire/test/junit/Repeat.java | 26 ++
.../test/junit/rules/ExpectedTimeoutRule.java | 164 +++++++++++
.../gemfire/test/junit/rules/RepeatRule.java | 57 ++++
.../tests/ExpectedTimeoutRuleJUnitTest.java | 206 ++++++++++++++
.../junit/rules/tests/JUnitRuleTestSuite.java | 16 ++
.../junit/rules/tests/RepeatRuleJUnitTest.java | 278 +++++++++++++++++++
.../RetryRuleGlobalWithErrorJUnitTest.java | 247 ++++++++++++++++
.../RetryRuleGlobalWithExceptionJUnitTest.java | 253 +++++++++++++++++
.../tests/RetryRuleLocalWithErrorJUnitTest.java | 206 ++++++++++++++
.../RetryRuleLocalWithExceptionJUnitTest.java | 221 +++++++++++++++
14 files changed, 1987 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/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
new file mode 100755
index 0000000..aaa6a84
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/assertj/AssertJExampleJUnitTest.java
@@ -0,0 +1,119 @@
+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/d0c03307/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
new file mode 100755
index 0000000..845c46d
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleDUnitTest.java
@@ -0,0 +1,59 @@
+package com.gemstone.gemfire.test.catchexception;
+
+import static com.googlecode.catchexception.CatchException.*;
+import static com.googlecode.catchexception.apis.BDDCatchException.when;
+import static org.assertj.core.api.BDDAssertions.*;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+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.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)
+public class CatchExceptionExampleDUnitTest extends DistributedTestCase {
+ private static final long serialVersionUID = 1L;
+
+ private static final String REMOTE_THROW_EXCEPTION_MESSAGE = "Throwing remoteThrowException";
+
+ @Test
+ public void testRemoteInvocationWithException() {
+ Host host = Host.getHost(0);
+ VM vm = host.getVM(0);
+
+ when(vm).invoke(new ThrowBasicTestException());
+
+ then(caughtException())
+ .isInstanceOf(RMIException.class)
+ .hasCause(new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE));
+ }
+
+ protected static class ThrowBasicTestException extends SerializableCallable<Object> {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public Object call() throws Exception {
+ throw new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE);
+ }
+ }
+
+ 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/d0c03307/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
new file mode 100755
index 0000000..73dc361
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionExampleJUnitTest.java
@@ -0,0 +1,99 @@
+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/d0c03307/gemfire-core/src/test/java/com/gemstone/gemfire/test/junitparams/JUnitParamsExampleJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/junitparams/JUnitParamsExampleJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/junitparams/JUnitParamsExampleJUnitTest.java
new file mode 100755
index 0000000..4e14fa7
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/junitparams/JUnitParamsExampleJUnitTest.java
@@ -0,0 +1,36 @@
+package com.gemstone.gemfire.test.junitparams;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.RunWith;
+
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
+@Category(UnitTest.class)
+@RunWith(JUnitParamsRunner.class)
+public class JUnitParamsExampleJUnitTest {
+ @Test
+ @Parameters({"17, false",
+ "22, true" })
+ public void personIsAdult(int age, boolean valid) throws Exception {
+ assertThat(true, is(true));
+ assertThat(new Person(age).isAdult(), is(valid));
+ }
+
+ protected static class Person {
+ private static final int MIN_AGE_OF_ADULT = 18;
+ private final int age;
+ public Person(final int age) {
+ this.age = age;
+ }
+ public Boolean isAdult() {
+ return this.age >= MIN_AGE_OF_ADULT;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Repeat.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Repeat.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Repeat.java
new file mode 100755
index 0000000..b76d160
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/Repeat.java
@@ -0,0 +1,26 @@
+package com.gemstone.gemfire.test.junit;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The Repeat class is a Java Annotation enabling an annotated test suite class test case method to be repeated
+ * a specified number of iterations.
+ *
+ * @author John Blum
+ * @see java.lang.annotation.Annotation
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.METHOD })
+@SuppressWarnings("unused")
+public @interface Repeat {
+
+ public static int DEFAULT = 1;
+
+ int value() default DEFAULT;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutRule.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutRule.java
new file mode 100755
index 0000000..bf6456f
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutRule.java
@@ -0,0 +1,164 @@
+package com.gemstone.gemfire.test.junit.rules;
+
+import static org.junit.Assert.assertThat;
+
+import java.util.concurrent.TimeUnit;
+
+import org.hamcrest.Matcher;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+
+/**
+ * Expect an Exception within a specified timeout.
+ *
+ * @author Kirk Lund
+ * @since 8.2
+ */
+public class ExpectedTimeoutRule implements TestRule {
+
+ /**
+ * @return a Rule that expects no timeout (identical to behavior without this Rule)
+ */
+ public static ExpectedTimeoutRule none() {
+ return new ExpectedTimeoutRule();
+ }
+
+ private ExpectedException delegate;
+ private boolean expectsThrowable;
+ private long minDuration;
+ private long maxDuration;
+ private TimeUnit timeUnit;
+
+ private ExpectedTimeoutRule() {
+ this.delegate = ExpectedException.none();
+ }
+
+ public ExpectedTimeoutRule expectMinimumDuration(final long minDuration) {
+ this.minDuration = minDuration;
+ return this;
+ }
+ public ExpectedTimeoutRule expectMaximumDuration(final long maxDuration) {
+ this.maxDuration = maxDuration;
+ return this;
+ }
+ public ExpectedTimeoutRule expectTimeUnit(final TimeUnit timeUnit) {
+ this.timeUnit = timeUnit;
+ return this;
+ }
+
+ public ExpectedTimeoutRule handleAssertionErrors() {
+ this.delegate.handleAssertionErrors();
+ return this;
+ }
+
+ public ExpectedTimeoutRule handleAssumptionViolatedExceptions() {
+ this.delegate.handleAssumptionViolatedExceptions();
+ return this;
+ }
+
+ /**
+ * Adds {@code matcher} to the list of requirements for any thrown
+ * exception.
+ */
+ public void expect(final Matcher<?> matcher) {
+ this.delegate.expect(matcher);
+ }
+
+ /**
+ * Adds to the list of requirements for any thrown exception that it should
+ * be an instance of {@code type}
+ */
+ public void expect(final Class<? extends Throwable> type) {
+ this.delegate.expect(type);
+ this.expectsThrowable = true;
+ }
+
+ /**
+ * Adds to the list of requirements for any thrown exception that it should
+ * <em>contain</em> string {@code substring}
+ */
+ public void expectMessage(final String substring) {
+ this.delegate.expectMessage(substring);
+ }
+
+ /**
+ * Adds {@code matcher} to the list of requirements for the message returned
+ * from any thrown exception.
+ */
+ public void expectMessage(final Matcher<String> matcher) {
+ this.delegate.expectMessage(matcher);
+ }
+
+ /**
+ * Adds {@code matcher} to the list of requirements for the cause of
+ * any thrown exception.
+ */
+ public void expectCause(final Matcher<? extends Throwable> expectedCause) {
+ this.delegate.expectCause(expectedCause);
+ }
+
+ public boolean expectsTimeout() {
+ return minDuration > 0 || maxDuration > 0;
+ }
+
+ public boolean expectsThrowable() {
+ return expectsThrowable = true;
+ }
+
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ Statement next = delegate.apply(base, description);
+ return new ExpectedTimeoutStatement(next);
+ }
+
+ private void handleTime(final Long duration) {
+ if (expectsTimeout()) {
+ assertThat(timeUnit.convert(duration, TimeUnit.NANOSECONDS), new TimeMatcher(timeUnit, minDuration, maxDuration));
+ }
+ }
+
+ private static class TimeMatcher extends org.hamcrest.TypeSafeMatcher<Long> {
+
+ private final TimeUnit timeUnit;
+ private final long minDuration;
+ private final long maxDuration;
+
+ public TimeMatcher(final TimeUnit timeUnit, final long minDuration, final long maxDuration) {
+ this.timeUnit = timeUnit;
+ this.minDuration = minDuration;
+ this.maxDuration = maxDuration;
+ }
+
+ @Override
+ public boolean matchesSafely(final Long duration) {
+ return duration >= this.minDuration && duration <= this.maxDuration;
+ }
+
+ @Override
+ public void describeTo(final org.hamcrest.Description description) {
+ description.appendText("expects duration to be greater than or equal to ")
+ .appendValue(this.minDuration)
+ .appendText(" and less than or equal to ")
+ .appendValue(this.maxDuration)
+ .appendText(" ")
+ .appendValue(this.timeUnit);
+ }
+ }
+
+ private class ExpectedTimeoutStatement extends Statement {
+ private final Statement next;
+
+ public ExpectedTimeoutStatement(final Statement base) {
+ next = base;
+ }
+
+ @Override
+ public void evaluate() throws Throwable {
+ long start = System.nanoTime();
+ next.evaluate();
+ handleTime(System.nanoTime() - start);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RepeatRule.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RepeatRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RepeatRule.java
new file mode 100755
index 0000000..ef66d48
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/RepeatRule.java
@@ -0,0 +1,57 @@
+package com.gemstone.gemfire.test.junit.rules;
+
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import com.gemstone.gemfire.test.junit.Repeat;
+
+/**
+ * The RepeatRule class is a JUnit TestRule that enables an appropriately @Repeat annotated test case method
+ * to be repeated a specified number of times.
+ *
+ * TODO: disallow 0 because @Retry(0) is equivalent to @Ignore apparently
+ *
+ * @author John Blum
+ * @see org.junit.rules.TestRule
+ * @see org.junit.runner.Description
+ * @see org.junit.runners.model.Statement
+ */
+@SuppressWarnings("unused")
+public class RepeatRule implements TestRule {
+
+ protected static final int DEFAULT_REPETITIONS = 1;
+
+ @Override
+ public Statement apply(final Statement statement, final Description description) {
+ return new Statement() {
+ @Override public void evaluate() throws Throwable {
+ RepeatRule.this.evaluate(statement, description);
+ }
+ };
+ }
+
+ protected void evaluate(final Statement statement, final Description description) throws Throwable {
+ if (isTest(description)) {
+ Repeat repeat = description.getAnnotation(Repeat.class);
+
+ for (int count = 0, repetitions = getRepetitions(repeat); count < repetitions; count++) {
+ statement.evaluate();
+ }
+ }
+ }
+
+ private int getRepetitions(final Repeat repeat) {
+ int repetitions = DEFAULT_REPETITIONS;
+
+ if (repeat != null) {
+ repetitions = repeat.value();
+ }
+
+ return repetitions;
+ }
+
+ private boolean isTest(final Description description) {
+ return (description.isSuite() || description.isTest());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/ExpectedTimeoutRuleJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/ExpectedTimeoutRuleJUnitTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/ExpectedTimeoutRuleJUnitTest.java
new file mode 100755
index 0000000..8a14f67
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/ExpectedTimeoutRuleJUnitTest.java
@@ -0,0 +1,206 @@
+package com.gemstone.gemfire.test.junit.rules.tests;
+
+import static org.hamcrest.core.StringContains.*;
+import static org.hamcrest.core.Is.*;
+import static org.hamcrest.core.IsInstanceOf.*;
+import static org.junit.Assert.*;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+import com.gemstone.gemfire.test.junit.rules.ExpectedTimeoutRule;
+
+/**
+ * Unit tests for ExpectedTimeout JUnit Rule.
+ *
+ * @author Kirk Lund
+ * @since 8.2
+ */
+@Category(UnitTest.class)
+public class ExpectedTimeoutRuleJUnitTest {
+
+ @Test
+ public void passesUnused() {
+ Result result = runTest(PassingTestShouldPassWhenUnused.class);
+
+ assertTrue(result.wasSuccessful());
+ }
+
+ @Test
+ public void failsWithoutExpectedException() {
+ Result result = runTest(FailsWithoutExpectedException.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString("Expected test to throw an instance of " + TimeoutException.class.getName()));
+ }
+
+ @Test
+ public void failsWithoutExpectedTimeoutException() {
+ Result result = runTest(FailsWithoutExpectedTimeoutException.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString("Expected test to throw (an instance of " + TimeoutException.class.getName() + " and exception with message a string containing \"" + FailsWithoutExpectedTimeoutException.message + "\")"));
+ }
+
+ @Test
+ public void failsWithExpectedTimeoutButWrongError() {
+ Result result = runTest(FailsWithExpectedTimeoutButWrongError.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(NullPointerException.class.getName()));
+ }
+
+ @Test
+ public void passesWithExpectedTimeoutAndTimeoutException() {
+ Result result = runTest(PassesWithExpectedTimeoutAndTimeoutException.class);
+
+ assertTrue(result.wasSuccessful());
+ }
+
+ @Test
+ public void failsWhenTimeoutIsEarly() {
+ Result result = runTest(FailsWhenTimeoutIsEarly.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString("Expected test to throw (an instance of " + TimeoutException.class.getName() + " and exception with message a string containing \"" + FailsWhenTimeoutIsEarly.message + "\")"));
+ }
+
+ @Test
+ public void failsWhenTimeoutIsLate() {
+ Result result = runTest(FailsWhenTimeoutIsLate.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString("Expected test to throw (an instance of " + TimeoutException.class.getName() + " and exception with message a string containing \"" + FailsWhenTimeoutIsLate.message + "\")"));
+ }
+
+ private static Result runTest(Class<?> test) {
+ JUnitCore junitCore = new JUnitCore();
+ return junitCore.run(Request.aClass(test).getRunner());
+ }
+
+ public static class AbstractExpectedTimeoutRuleTest {
+ @Rule
+ public ExpectedTimeoutRule timeout = ExpectedTimeoutRule.none();
+ }
+
+ public static class PassingTestShouldPassWhenUnused extends AbstractExpectedTimeoutRuleTest {
+ @Test
+ public void passesUnused() throws Exception {
+ }
+ }
+
+ public static class FailsWithoutExpectedException extends AbstractExpectedTimeoutRuleTest {
+ @Test
+ public void failsWithoutExpectedException() throws Exception {
+ timeout.expect(TimeoutException.class);
+ }
+ }
+
+ public static class FailsWithoutExpectedTimeoutException extends AbstractExpectedTimeoutRuleTest {
+ public static final String message = "this is a message for FailsWithoutExpectedTimeoutException";
+ @Test
+ public void failsWithoutExpectedTimeoutAndTimeoutException() throws Exception {
+ timeout.expect(TimeoutException.class);
+ timeout.expectMessage(message);
+ timeout.expectMinimumDuration(10);
+ timeout.expectMaximumDuration(1000);
+ timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
+ Thread.sleep(100);
+ }
+ }
+
+ public static class FailsWithExpectedTimeoutButWrongError extends AbstractExpectedTimeoutRuleTest {
+ public static final String message = "this is a message for FailsWithExpectedTimeoutButWrongError";
+ @Test
+ public void failsWithExpectedTimeoutButWrongError() throws Exception {
+ timeout.expect(TimeoutException.class);
+ timeout.expectMessage(message);
+ timeout.expectMinimumDuration(10);
+ timeout.expectMaximumDuration(1000);
+ timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
+ Thread.sleep(100);
+ throw new NullPointerException();
+ }
+ }
+
+ public static class PassesWithExpectedTimeoutAndTimeoutException extends AbstractExpectedTimeoutRuleTest {
+ public static final String message = "this is a message for PassesWithExpectedTimeoutAndTimeoutException";
+ public static final Class<TimeoutException> exceptionClass = TimeoutException.class;
+ @Test
+ public void passesWithExpectedTimeoutAndTimeoutException() throws Exception {
+ timeout.expect(exceptionClass);
+ timeout.expectMessage(message);
+ timeout.expectMinimumDuration(10);
+ timeout.expectMaximumDuration(1000);
+ timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
+ Thread.sleep(100);
+ throw new TimeoutException(message);
+ }
+ }
+
+ public static class FailsWhenTimeoutIsEarly extends AbstractExpectedTimeoutRuleTest {
+ public static final String message = "this is a message for FailsWhenTimeoutIsEarly";
+ @Test
+ public void failsWhenTimeoutIsEarly() throws Exception {
+ timeout.expect(TimeoutException.class);
+ timeout.expectMessage(message);
+ timeout.expectMinimumDuration(1000);
+ timeout.expectMaximumDuration(2000);
+ timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
+ Thread.sleep(10);
+ }
+ }
+
+ public static class FailsWhenTimeoutIsLate extends AbstractExpectedTimeoutRuleTest {
+ public static final String message = "this is a message for FailsWhenTimeoutIsLate";
+ @Test
+ public void failsWhenTimeoutIsLate() throws Exception {
+ timeout.expect(TimeoutException.class);
+ timeout.expectMessage(message);
+ timeout.expectMinimumDuration(10);
+ timeout.expectMaximumDuration(20);
+ timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
+ Thread.sleep(100);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/JUnitRuleTestSuite.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/JUnitRuleTestSuite.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/JUnitRuleTestSuite.java
new file mode 100755
index 0000000..ff102f7
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/JUnitRuleTestSuite.java
@@ -0,0 +1,16 @@
+package com.gemstone.gemfire.test.junit.rules.tests;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+
+@RunWith(Suite.class)
+@Suite.SuiteClasses({
+ ExpectedTimeoutRuleJUnitTest.class,
+ RepeatRuleJUnitTest.class,
+ RetryRuleGlobalWithErrorJUnitTest.class,
+ RetryRuleGlobalWithExceptionJUnitTest.class,
+ RetryRuleLocalWithErrorJUnitTest.class,
+ RetryRuleLocalWithExceptionJUnitTest.class,
+})
+public class JUnitRuleTestSuite {
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RepeatRuleJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RepeatRuleJUnitTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RepeatRuleJUnitTest.java
new file mode 100755
index 0000000..5e69f03
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RepeatRuleJUnitTest.java
@@ -0,0 +1,278 @@
+package com.gemstone.gemfire.test.junit.rules.tests;
+
+import static org.hamcrest.Matchers.*;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+import com.gemstone.gemfire.test.junit.Repeat;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+import com.gemstone.gemfire.test.junit.rules.RepeatRule;
+
+/**
+ * Unit tests for Repeat JUnit Rule.
+ *
+ * @author Kirk Lund
+ */
+@Category(UnitTest.class)
+public class RepeatRuleJUnitTest {
+
+ private static final String ASSERTION_ERROR_MESSAGE = "failing test";
+
+ @Test
+ public void failingTestShouldFailOneTimeWhenRepeatIsUnused() {
+ Result result = runTest(FailingTestShouldFailOneTimeWhenRepeatIsUnused.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(ASSERTION_ERROR_MESSAGE));
+ assertThat(FailingTestShouldFailOneTimeWhenRepeatIsUnused.count, is(1));
+ }
+
+ @Test
+ public void passingTestShouldPassOneTimeWhenRepeatIsUnused() {
+ Result result = runTest(PassingTestShouldPassOneTimeWhenRepeatIsUnused.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassingTestShouldPassOneTimeWhenRepeatIsUnused.count, is(1));
+ }
+
+ @Test
+ public void failingTestShouldBeSkippedWhenRepeatIsZero() {
+ Result result = runTest(FailingTestShouldBeSkippedWhenRepeatIsZero.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(FailingTestShouldBeSkippedWhenRepeatIsZero.count, is(0));
+ }
+
+ @Test
+ public void passingTestShouldBeSkippedWhenRepeatIsZero() {
+ Result result = runTest(PassingTestShouldBeSkippedWhenRepeatIsZero.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassingTestShouldBeSkippedWhenRepeatIsZero.count, is(0));
+ }
+
+ @Test
+ public void failingTestShouldFailOneTimeWhenRepeatIsOne() {
+ Result result = runTest(FailingTestShouldFailOneTimeWhenRepeatIsOne.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(ASSERTION_ERROR_MESSAGE));
+ assertThat(FailingTestShouldFailOneTimeWhenRepeatIsOne.count, is(1));
+ }
+
+ @Test
+ public void passingTestShouldPassOneTimeWhenRepeatIsOne() {
+ Result result = runTest(PassingTestShouldPassOneTimeWhenRepeatIsOne.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassingTestShouldPassOneTimeWhenRepeatIsOne.count, is(1));
+ }
+
+ @Test
+ public void failingTestShouldFailOneTimeWhenRepeatIsTwo() {
+ Result result = runTest(FailingTestShouldFailOneTimeWhenRepeatIsTwo.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(ASSERTION_ERROR_MESSAGE));
+ assertThat(FailingTestShouldFailOneTimeWhenRepeatIsTwo.count, is(1));
+ }
+
+ @Test
+ public void passingTestShouldPassTwoTimesWhenRepeatIsTwo() {
+ Result result = runTest(PassingTestShouldPassTwoTimesWhenRepeatIsTwo.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassingTestShouldPassTwoTimesWhenRepeatIsTwo.count, is(2));
+ }
+
+ @Test
+ public void failingTestShouldFailOneTimeWhenRepeatIsThree() {
+ Result result = runTest(FailingTestShouldFailOneTimeWhenRepeatIsThree.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(ASSERTION_ERROR_MESSAGE));
+ assertThat(FailingTestShouldFailOneTimeWhenRepeatIsThree.count, is(1));
+ }
+
+ @Test
+ public void passingTestShouldPassThreeTimesWhenRepeatIsThree() {
+ Result result = runTest(PassingTestShouldPassThreeTimesWhenRepeatIsThree.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassingTestShouldPassThreeTimesWhenRepeatIsThree.count, is(3));
+ }
+
+ private static Result runTest(Class<?> test) {
+ JUnitCore junitCore = new JUnitCore();
+ return junitCore.run(Request.aClass(test).getRunner());
+ }
+
+ public static class FailingTestShouldFailOneTimeWhenRepeatIsUnused {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ public void doTest() throws Exception {
+ count++;
+ fail(ASSERTION_ERROR_MESSAGE);
+ }
+ }
+
+ public static class PassingTestShouldPassOneTimeWhenRepeatIsUnused {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ public void doTest() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailingTestShouldBeSkippedWhenRepeatIsZero {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ @Repeat(0)
+ public void doTest() throws Exception {
+ count++;
+ fail(ASSERTION_ERROR_MESSAGE);
+ }
+ }
+
+ public static class PassingTestShouldBeSkippedWhenRepeatIsZero {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ @Repeat(0)
+ public void doTest() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailingTestShouldFailOneTimeWhenRepeatIsOne {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ @Repeat(1)
+ public void doTest() throws Exception {
+ count++;
+ fail(ASSERTION_ERROR_MESSAGE);
+ }
+ }
+
+ public static class PassingTestShouldPassOneTimeWhenRepeatIsOne {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ @Repeat(1)
+ public void doTest() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailingTestShouldFailOneTimeWhenRepeatIsTwo {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ @Repeat(2)
+ public void doTest() throws Exception {
+ count++;
+ fail(ASSERTION_ERROR_MESSAGE);
+ }
+ }
+
+ public static class PassingTestShouldPassTwoTimesWhenRepeatIsTwo {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ @Repeat(2)
+ public void doTest() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailingTestShouldFailOneTimeWhenRepeatIsThree {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ @Repeat(3)
+ public void doTest() throws Exception {
+ count++;
+ fail(ASSERTION_ERROR_MESSAGE);
+ }
+ }
+
+ public static class PassingTestShouldPassThreeTimesWhenRepeatIsThree {
+ protected static int count = 0;
+
+ @Rule
+ public RepeatRule repeat = new RepeatRule();
+
+ @Test
+ @Repeat(3)
+ public void doTest() throws Exception {
+ count++;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleGlobalWithErrorJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleGlobalWithErrorJUnitTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleGlobalWithErrorJUnitTest.java
new file mode 100755
index 0000000..ce473e8
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleGlobalWithErrorJUnitTest.java
@@ -0,0 +1,247 @@
+package com.gemstone.gemfire.test.junit.rules.tests;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+import com.gemstone.gemfire.test.junit.Retry;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+import com.gemstone.gemfire.test.junit.rules.RetryRule;
+
+/**
+ * Unit tests for Retry JUnit Rule involving global scope (ie Rule affects all
+ * tests in the test case) with failures due to an Exception.
+ *
+ * @author Kirk Lund
+ */
+@Category(UnitTest.class)
+public class RetryRuleGlobalWithErrorJUnitTest {
+
+ @Test
+ public void zeroIsIllegal() {
+ Result result = runTest(ZeroIsIllegal.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(IllegalArgumentException.class)));
+ assertThat(failure.getException().getMessage(), containsString("Retry count must be greater than zero"));
+ assertThat(ZeroIsIllegal.count, is(0));
+ }
+
+ @Test
+ public void failsWithOne() {
+ Result result = runTest(FailsWithOne.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsWithOne.message));
+ assertThat(FailsWithOne.count, is(1));
+ }
+
+ @Test
+ public void passesWithOne() {
+ Result result = runTest(PassesWithOne.class);
+
+ assertTrue(result.wasSuccessful());
+ }
+
+ @Test
+ public void passesWithUnused() {
+ Result result = runTest(PassesWhenUnused.class);
+
+ assertTrue(result.wasSuccessful());
+ }
+
+ @Test
+ public void failsOnSecondAttempt() {
+ Result result = runTest(FailsOnSecondAttempt.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsOnSecondAttempt.message));
+ assertThat(FailsOnSecondAttempt.count, is(2));
+ }
+
+ @Test
+ public void passesOnSecondAttempt() {
+ Result result = runTest(PassesOnSecondAttempt.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesOnSecondAttempt.count, is(2));
+ }
+
+ @Test
+ public void failsOnThirdAttempt() {
+ Result result = runTest(FailsOnThirdAttempt.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsOnThirdAttempt.message));
+ assertThat(FailsOnThirdAttempt.count, is(3));
+ }
+
+ @Test
+ public void passesOnThirdAttempt() {
+ Result result = runTest(PassesOnThirdAttempt.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesOnThirdAttempt.count, is(3));
+ }
+
+ private static Result runTest(Class<?> test) {
+ JUnitCore junitCore = new JUnitCore();
+ return junitCore.run(Request.aClass(test).getRunner());
+ }
+
+ public static class ZeroIsIllegal {
+ protected static int count;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(0);
+
+ @Test
+ public void zeroIsIllegal() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailsWithOne {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(1);
+
+ @Test
+ public void failsWithOne() throws Exception {
+ count++;
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+
+ public static class PassesWithOne {
+ protected static int count;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(1);
+
+ @Test
+ public void passesWithOne() throws Exception {
+ count++;
+ }
+ }
+
+ public static class PassesWhenUnused {
+ protected static int count;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(2);
+
+ @Test
+ public void passesWithUnused() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailsOnSecondAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(2);
+
+ @Test
+ @Retry(2)
+ public void failsOnSecondAttempt() {
+ count++;
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+
+ public static class PassesOnSecondAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(2);
+
+ @Test
+ @Retry(2)
+ public void failsOnSecondAttempt() {
+ count++;
+ if (count < 2) {
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+ }
+
+ public static class FailsOnThirdAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(3);
+
+ @Test
+ @Retry(3)
+ public void failsOnThirdAttempt() {
+ count++;
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+
+ public static class PassesOnThirdAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(3);
+
+ @Test
+ public void failsOnThirdAttempt() {
+ count++;
+ if (count < 3) {
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleGlobalWithExceptionJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleGlobalWithExceptionJUnitTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleGlobalWithExceptionJUnitTest.java
new file mode 100755
index 0000000..b67880c
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleGlobalWithExceptionJUnitTest.java
@@ -0,0 +1,253 @@
+package com.gemstone.gemfire.test.junit.rules.tests;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+import com.gemstone.gemfire.test.junit.Retry;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+import com.gemstone.gemfire.test.junit.rules.RetryRule;
+
+/**
+ * Unit tests for Retry JUnit Rule involving global scope (ie Rule affects all
+ * tests in the test case) with failures due to an Exception.
+ *
+ * @author Kirk Lund
+ */
+@Category(UnitTest.class)
+public class RetryRuleGlobalWithExceptionJUnitTest {
+
+ @Test
+ public void zeroIsIllegal() {
+ Result result = runTest(ZeroIsIllegal.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(IllegalArgumentException.class)));
+ assertThat(failure.getException().getMessage(), containsString("Retry count must be greater than zero"));
+ assertThat(ZeroIsIllegal.count, is(0));
+ }
+
+ @Test
+ public void failsWithOne() {
+ Result result = runTest(FailsWithOne.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(CustomException.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsWithOne.message));
+ assertThat(FailsWithOne.count, is(1));
+ }
+
+ @Test
+ public void passesWithOne() {
+ Result result = runTest(PassesWithOne.class);
+
+ assertTrue(result.wasSuccessful());
+ }
+
+ @Test
+ public void passesWithUnused() {
+ Result result = runTest(PassesWhenUnused.class);
+
+ assertTrue(result.wasSuccessful());
+ }
+
+ @Test
+ public void failsOnSecondAttempt() {
+ Result result = runTest(FailsOnSecondAttempt.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(CustomException.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsOnSecondAttempt.message));
+ assertThat(FailsOnSecondAttempt.count, is(2));
+ }
+
+ @Test
+ public void passesOnSecondAttempt() {
+ Result result = runTest(PassesOnSecondAttempt.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesOnSecondAttempt.count, is(2));
+ }
+
+ @Test
+ public void failsOnThirdAttempt() {
+ Result result = runTest(FailsOnThirdAttempt.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(CustomException.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsOnThirdAttempt.message));
+ assertThat(FailsOnThirdAttempt.count, is(3));
+ }
+
+ @Test
+ public void passesOnThirdAttempt() {
+ Result result = runTest(PassesOnThirdAttempt.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesOnThirdAttempt.count, is(3));
+ }
+
+ private static Result runTest(Class<?> test) {
+ JUnitCore junitCore = new JUnitCore();
+ return junitCore.run(Request.aClass(test).getRunner());
+ }
+
+ public static class CustomException extends Exception {
+ private static final long serialVersionUID = 1L;
+ public CustomException(final String message) {
+ super(message);
+ }
+ }
+
+ public static class ZeroIsIllegal {
+ protected static int count;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(0);
+
+ @Test
+ public void zeroIsIllegal() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailsWithOne {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(1);
+
+ @Test
+ public void failsWithOne() throws Exception {
+ count++;
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+
+ public static class PassesWithOne {
+ protected static int count;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(1);
+
+ @Test
+ public void passesWithOne() throws Exception {
+ count++;
+ }
+ }
+
+ public static class PassesWhenUnused {
+ protected static int count;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(2);
+
+ @Test
+ public void passesWithUnused() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailsOnSecondAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(2);
+
+ @Test
+ @Retry(2)
+ public void failsOnSecondAttempt() throws Exception {
+ count++;
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+
+ public static class PassesOnSecondAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(2);
+
+ @Test
+ @Retry(2)
+ public void failsOnSecondAttempt() throws Exception {
+ count++;
+ if (count < 2) {
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+ }
+
+ public static class FailsOnThirdAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(3);
+
+ @Test
+ @Retry(3)
+ public void failsOnThirdAttempt() throws Exception {
+ count++;
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+
+ public static class PassesOnThirdAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule(3);
+
+ @Test
+ public void failsOnThirdAttempt() throws Exception {
+ count++;
+ if (count < 3) {
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleLocalWithErrorJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleLocalWithErrorJUnitTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleLocalWithErrorJUnitTest.java
new file mode 100755
index 0000000..b06575c
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleLocalWithErrorJUnitTest.java
@@ -0,0 +1,206 @@
+package com.gemstone.gemfire.test.junit.rules.tests;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+import com.gemstone.gemfire.test.junit.Retry;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+import com.gemstone.gemfire.test.junit.rules.RetryRule;
+
+/**
+ * Unit tests for Retry JUnit Rule involving local scope (ie Rule affects
+ * test methods annotated with @Retry) with failures due to an Error.
+ *
+ * @author Kirk Lund
+ */
+@Category(UnitTest.class)
+public class RetryRuleLocalWithErrorJUnitTest {
+
+ @Test
+ public void failsUnused() {
+ Result result = runTest(FailsUnused.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsUnused.message));
+ assertThat(FailsUnused.count, is(1));
+ }
+
+ @Test
+ public void passesUnused() {
+ Result result = runTest(PassesUnused.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesUnused.count, is(1));
+ }
+
+ @Test
+ public void failsOnSecondAttempt() {
+ Result result = runTest(FailsOnSecondAttempt.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsOnSecondAttempt.message));
+ assertThat(FailsOnSecondAttempt.count, is(2));
+ }
+
+ @Test
+ public void passesOnSecondAttempt() {
+ Result result = runTest(PassesOnSecondAttempt.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesOnSecondAttempt.count, is(2));
+ }
+
+ @Test
+ public void failsOnThirdAttempt() {
+ Result result = runTest(FailsOnThirdAttempt.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsOnThirdAttempt.message));
+ assertThat(FailsOnThirdAttempt.count, is(3));
+ }
+
+ @Test
+ public void passesOnThirdAttempt() {
+ Result result = runTest(PassesOnThirdAttempt.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesOnThirdAttempt.count, is(3));
+ }
+
+ private static Result runTest(Class<?> test) {
+ JUnitCore junitCore = new JUnitCore();
+ return junitCore.run(Request.aClass(test).getRunner());
+ }
+
+ public static class FailsUnused {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ public void failsUnused() throws Exception {
+ count++;
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+
+ public static class PassesUnused {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ public void passesUnused() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailsOnSecondAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ @Retry(2)
+ public void failsOnSecondAttempt() {
+ count++;
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+
+ public static class PassesOnSecondAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ @Retry(2)
+ public void failsOnSecondAttempt() {
+ count++;
+ if (count < 2) {
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+ }
+
+ public static class FailsOnThirdAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ @Retry(3)
+ public void failsOnThirdAttempt() {
+ count++;
+
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+
+ public static class PassesOnThirdAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ @Retry(3)
+ public void failsOnThirdAttempt() {
+ count++;
+
+ if (count < 3) {
+ message = "Failing " + count;
+ fail(message);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/d0c03307/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleLocalWithExceptionJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleLocalWithExceptionJUnitTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleLocalWithExceptionJUnitTest.java
new file mode 100755
index 0000000..4cff4bb
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/tests/RetryRuleLocalWithExceptionJUnitTest.java
@@ -0,0 +1,221 @@
+package com.gemstone.gemfire.test.junit.rules.tests;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.hamcrest.core.StringContains.containsString;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.List;
+
+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.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+import com.gemstone.gemfire.test.junit.Retry;
+import com.gemstone.gemfire.test.junit.categories.UnitTest;
+import com.gemstone.gemfire.test.junit.rules.RetryRule;
+import com.gemstone.gemfire.test.junit.rules.tests.RetryRuleLocalWithErrorJUnitTest.FailsOnSecondAttempt;
+import com.gemstone.gemfire.test.junit.rules.tests.RetryRuleLocalWithErrorJUnitTest.FailsOnThirdAttempt;
+import com.gemstone.gemfire.test.junit.rules.tests.RetryRuleLocalWithErrorJUnitTest.FailsUnused;
+import com.gemstone.gemfire.test.junit.rules.tests.RetryRuleLocalWithErrorJUnitTest.PassesOnSecondAttempt;
+import com.gemstone.gemfire.test.junit.rules.tests.RetryRuleLocalWithErrorJUnitTest.PassesOnThirdAttempt;
+import com.gemstone.gemfire.test.junit.rules.tests.RetryRuleLocalWithErrorJUnitTest.PassesUnused;
+
+/**
+ * Unit tests for Retry JUnit Rule involving local scope (ie Rule affects
+ * test methods annotated with @Retry) with failures due to an Exception.
+ *
+ * @author Kirk Lund
+ */
+@Category(UnitTest.class)
+public class RetryRuleLocalWithExceptionJUnitTest {
+
+ @Test
+ public void failsUnused() {
+ Result result = runTest(FailsUnused.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals("Failures: " + failures, 1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(CustomException.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsUnused.message));
+ assertThat(FailsUnused.count, is(1));
+ }
+
+ @Test
+ public void passesUnused() {
+ Result result = runTest(PassesUnused.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesUnused.count, is(1));
+ }
+
+ @Test
+ public void failsOnSecondAttempt() {
+ Result result = runTest(FailsOnSecondAttempt.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(CustomException.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsOnSecondAttempt.message));
+ assertThat(FailsOnSecondAttempt.count, is(2));
+ }
+
+ @Test
+ public void passesOnSecondAttempt() {
+ Result result = runTest(PassesOnSecondAttempt.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesOnSecondAttempt.count, is(2));
+ }
+
+ @Test
+ public void failsOnThirdAttempt() {
+ Result result = runTest(FailsOnThirdAttempt.class);
+
+ assertFalse(result.wasSuccessful());
+
+ List<Failure> failures = result.getFailures();
+ assertEquals(1, failures.size());
+
+ Failure failure = failures.get(0);
+ assertThat(failure.getException(), is(instanceOf(CustomException.class)));
+ assertThat(failure.getException().getMessage(), containsString(FailsOnThirdAttempt.message));
+ assertThat(FailsOnThirdAttempt.count, is(3));
+ }
+
+ @Test
+ public void passesOnThirdAttempt() {
+ Result result = runTest(PassesOnThirdAttempt.class);
+
+ assertTrue(result.wasSuccessful());
+ assertThat(PassesOnThirdAttempt.count, is(3));
+ }
+
+ private static Result runTest(Class<?> test) {
+ JUnitCore junitCore = new JUnitCore();
+ return junitCore.run(Request.aClass(test).getRunner());
+ }
+
+ public static class CustomException extends Exception {
+ private static final long serialVersionUID = 1L;
+ public CustomException(final String message) {
+ super(message);
+ }
+ }
+
+ public static class FailsUnused {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ public void failsUnused() throws Exception {
+ count++;
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+
+ public static class PassesUnused {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ public void passesUnused() throws Exception {
+ count++;
+ }
+ }
+
+ public static class FailsOnSecondAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ @Retry(2)
+ public void failsOnSecondAttempt() throws Exception {
+ count++;
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+
+ public static class PassesOnSecondAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ @Retry(2)
+ public void failsOnSecondAttempt() throws Exception {
+ count++;
+ if (count < 2) {
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+ }
+
+ public static class FailsOnThirdAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ @Retry(3)
+ public void failsOnThirdAttempt() throws Exception {
+ count++;
+
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+
+ public static class PassesOnThirdAttempt {
+ protected static int count;
+ protected static String message;
+
+ @Rule
+ public RetryRule retryRule = new RetryRule();
+
+ @Test
+ @Retry(3)
+ public void failsOnThirdAttempt() throws Exception {
+ count++;
+
+ if (count < 3) {
+ message = "Failing " + count;
+ throw new CustomException(message);
+ }
+ }
+ }
+}
[9/9] incubator-geode git commit: Conditional ignore rule
Posted by kl...@apache.org.
Conditional ignore rule
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/c396e94a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/c396e94a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/c396e94a
Branch: refs/heads/feature/GEODE-217
Commit: c396e94a1a12e27ffc49941c87560779235bf86e
Parents: d0c0330
Author: Kirk Lund <kl...@pivotal.io>
Authored: Fri Aug 21 13:28:39 2015 -0700
Committer: Kirk Lund <kl...@pivotal.io>
Committed: Fri Aug 21 13:28:39 2015 -0700
----------------------------------------------------------------------
.../gemfire/test/junit/ConditionalIgnore.java | 33 ++++++
.../gemfire/test/junit/IgnoreCondition.java | 16 +++
.../gemfire/test/junit/IgnoreUntil.java | 33 ++++++
.../test/junit/rules/ConditionalIgnoreRule.java | 106 +++++++++++++++++++
.../test/junit/rules/IgnoreUntilRule.java | 106 +++++++++++++++++++
.../junit/support/DefaultIgnoreCondition.java | 41 +++++++
.../IgnoreConditionEvaluationException.java | 27 +++++
7 files changed, 362 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c396e94a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/ConditionalIgnore.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/ConditionalIgnore.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/ConditionalIgnore.java
new file mode 100755
index 0000000..0a3f63d
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/ConditionalIgnore.java
@@ -0,0 +1,33 @@
+package com.gemstone.gemfire.test.junit;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.gemstone.gemfire.test.junit.support.DefaultIgnoreCondition;
+
+/**
+ * The ConditionalIgnore class is a Java Annotation used to annotated a test suite class test case method in order to
+ * conditionally ignore the test case for a fixed amount of time, or based on a predetermined condition provided by
+ * the IgnoreCondition interface.
+ *
+ * @author John Blum
+ * @see java.lang.annotation.Annotation
+ * @see com.gemstone.gemfire.test.junit.IgnoreCondition
+ * @see com.gemstone.gemfire.test.junit.support.DefaultIgnoreCondition
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@SuppressWarnings("unused")
+public @interface ConditionalIgnore {
+
+ Class<? extends IgnoreCondition> condition() default DefaultIgnoreCondition.class;
+
+ String until() default "1970-01-01";
+
+ String value() default "";
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c396e94a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreCondition.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreCondition.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreCondition.java
new file mode 100755
index 0000000..689d0b7
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreCondition.java
@@ -0,0 +1,16 @@
+package com.gemstone.gemfire.test.junit;
+
+import org.junit.runner.Description;
+
+/**
+ * The IgnoreCondition class...
+ *
+ * @author John Blum
+ * @see org.junit.runner.Description
+ */
+@SuppressWarnings("unused")
+public interface IgnoreCondition {
+
+ boolean evaluate(Description testCaseDescription);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c396e94a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreUntil.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreUntil.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreUntil.java
new file mode 100755
index 0000000..66ab929
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/IgnoreUntil.java
@@ -0,0 +1,33 @@
+package com.gemstone.gemfire.test.junit;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.gemstone.gemfire.test.junit.support.DefaultIgnoreCondition;
+
+/**
+ * The IgnoreUntil class is a Java Annotation used to annotated a test suite class test case method in order to
+ * conditionally ignore the test case for a fixed amount of time, or based on a predetermined condition provided by
+ * the IgnoreCondition interface.
+ *
+ * @author John Blum
+ * @see java.lang.annotation.Annotation
+ * @see com.gemstone.gemfire.test.junit.IgnoreCondition
+ * @see com.gemstone.gemfire.test.junit.support.DefaultIgnoreCondition
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ ElementType.TYPE, ElementType.METHOD })
+@SuppressWarnings("unused")
+public @interface IgnoreUntil {
+
+ Class<? extends IgnoreCondition> condition() default DefaultIgnoreCondition.class;
+
+ String deadline() default "1970-01-01";
+
+ String value() default "";
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c396e94a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ConditionalIgnoreRule.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ConditionalIgnoreRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ConditionalIgnoreRule.java
new file mode 100755
index 0000000..9d73e32
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ConditionalIgnoreRule.java
@@ -0,0 +1,106 @@
+package com.gemstone.gemfire.test.junit.rules;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+import org.junit.AssumptionViolatedException;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import com.gemstone.gemfire.test.junit.ConditionalIgnore;
+import com.gemstone.gemfire.test.junit.IgnoreCondition;
+import com.gemstone.gemfire.test.junit.support.IgnoreConditionEvaluationException;
+
+/**
+ * The ConditionalIgnoreRule class...
+ *
+ * @author John Blum
+ * @see org.junit.rules.TestRule
+ * @see org.junit.runner.Description
+ * @see org.junit.runners.model.Statement
+ * @see com.gemstone.gemfire.test.junit.ConditionalIgnore
+ * @see com.gemstone.gemfire.test.junit.IgnoreCondition
+ */
+@SuppressWarnings("unused")
+public class ConditionalIgnoreRule implements TestRule {
+
+ protected static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd";
+ protected static final String DEFAULT_MESSAGE = "Ignoring test case (%1$s) of test class (%2$s)!";
+
+ protected static final DateFormat DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT_PATTERN);
+
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return new Statement() {
+ @Override public void evaluate() throws Throwable {
+ ConditionalIgnoreRule.this.evaluate(base, description);
+ }
+ };
+ }
+
+ public final void evaluate(Statement statement, Description description) throws Throwable {
+ throwOnIgnoreTest(statement, description).evaluate();
+ }
+
+ protected Statement throwOnIgnoreTest(Statement statement, Description description) {
+ if (isTest(description)) {
+ boolean ignoreTest = false;
+ String message = "";
+
+ ConditionalIgnore testCaseAnnotation = description.getAnnotation(ConditionalIgnore.class);
+
+ if (testCaseAnnotation != null) {
+ ignoreTest = evaluate(testCaseAnnotation, description);
+ message = testCaseAnnotation.value();
+ }
+ else if (description.getTestClass().isAnnotationPresent(ConditionalIgnore.class)) {
+ ConditionalIgnore testClassAnnotation = description.getTestClass().getAnnotation(ConditionalIgnore.class);
+
+ ignoreTest = evaluate(testClassAnnotation, description);
+ message = testClassAnnotation.value();
+ }
+
+ if (ignoreTest) {
+ throw new AssumptionViolatedException(format(message, description));
+ }
+ }
+
+ return statement;
+ }
+
+ protected boolean isTest(final Description description) {
+ return (description.isSuite() || description.isTest());
+ }
+
+ protected String format(String message, Description description) {
+ message = (!message.isEmpty() ? message : DEFAULT_MESSAGE);
+ return String.format(message, description.getMethodName(), description.getClassName());
+ }
+
+ protected boolean evaluate(ConditionalIgnore conditionalIgnoreAnnotation, Description description) {
+ return (evaluateCondition(conditionalIgnoreAnnotation.condition(), description)
+ || evaluateUntil(conditionalIgnoreAnnotation.until()));
+ }
+
+ protected boolean evaluateCondition(Class<? extends IgnoreCondition> ignoreConditionType, Description description) {
+ try {
+ return ignoreConditionType.newInstance().evaluate(description);
+ }
+ catch (Exception e) {
+ throw new IgnoreConditionEvaluationException(String.format("failed to evaluate IgnoreCondition: %1$s",
+ ignoreConditionType.getName()), e);
+ }
+ }
+
+ protected boolean evaluateUntil(String timestamp) {
+ try {
+ return DATE_FORMAT.parse(timestamp).after(Calendar.getInstance().getTime());
+ }
+ catch (ParseException e) {
+ return false;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c396e94a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/IgnoreUntilRule.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/IgnoreUntilRule.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/IgnoreUntilRule.java
new file mode 100755
index 0000000..fd35ad7
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/IgnoreUntilRule.java
@@ -0,0 +1,106 @@
+package com.gemstone.gemfire.test.junit.rules;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+import org.junit.AssumptionViolatedException;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import com.gemstone.gemfire.test.junit.IgnoreUntil;
+import com.gemstone.gemfire.test.junit.IgnoreCondition;
+import com.gemstone.gemfire.test.junit.support.IgnoreConditionEvaluationException;
+
+/**
+ * The IgnoreUntilRule class...
+ *
+ * @author John Blum
+ * @see org.junit.rules.TestRule
+ * @see org.junit.runner.Description
+ * @see org.junit.runners.model.Statement
+ * @see com.gemstone.gemfire.test.junit.IgnoreUntil
+ * @see com.gemstone.gemfire.test.junit.IgnoreCondition
+ */
+@SuppressWarnings("unused")
+public class IgnoreUntilRule implements TestRule {
+
+ protected static final String DATE_FORMAT_PATTERN = "yyyy-MM-dd";
+ protected static final String DEFAULT_MESSAGE = "Ignoring test case (%1$s) of test class (%2$s)!";
+
+ protected static final DateFormat DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT_PATTERN);
+
+ @Override
+ public Statement apply(final Statement base, final Description description) {
+ return new Statement() {
+ @Override public void evaluate() throws Throwable {
+ IgnoreUntilRule.this.evaluate(base, description);
+ }
+ };
+ }
+
+ public final void evaluate(Statement statement, Description description) throws Throwable {
+ throwOnIgnoreTest(statement, description).evaluate();
+ }
+
+ protected Statement throwOnIgnoreTest(Statement statement, Description description) {
+ if (isTest(description)) {
+ boolean ignoreTest = false;
+ String message = "";
+
+ IgnoreUntil testCaseAnnotation = description.getAnnotation(IgnoreUntil.class);
+
+ if (testCaseAnnotation != null) {
+ ignoreTest = evaluate(testCaseAnnotation, description);
+ message = testCaseAnnotation.value();
+ }
+ else if (description.getTestClass().isAnnotationPresent(IgnoreUntil.class)) {
+ IgnoreUntil testClassAnnotation = description.getTestClass().getAnnotation(IgnoreUntil.class);
+
+ ignoreTest = evaluate(testClassAnnotation, description);
+ message = testClassAnnotation.value();
+ }
+
+ if (ignoreTest) {
+ throw new AssumptionViolatedException(format(message, description));
+ }
+ }
+
+ return statement;
+ }
+
+ protected boolean isTest(final Description description) {
+ return (description.isSuite() || description.isTest());
+ }
+
+ protected String format(String message, Description description) {
+ message = (!message.isEmpty() ? message : DEFAULT_MESSAGE);
+ return String.format(message, description.getMethodName(), description.getClassName());
+ }
+
+ protected boolean evaluate(IgnoreUntil conditionalIgnoreAnnotation, Description description) {
+ return (evaluateCondition(conditionalIgnoreAnnotation.condition(), description)
+ || evaluateUntil(conditionalIgnoreAnnotation.deadline()));
+ }
+
+ protected boolean evaluateCondition(Class<? extends IgnoreCondition> ignoreConditionType, Description description) {
+ try {
+ return ignoreConditionType.newInstance().evaluate(description);
+ }
+ catch (Exception e) {
+ throw new IgnoreConditionEvaluationException(String.format("failed to evaluate IgnoreCondition: %1$s",
+ ignoreConditionType.getName()), e);
+ }
+ }
+
+ protected boolean evaluateUntil(String timestamp) {
+ try {
+ return DATE_FORMAT.parse(timestamp).after(Calendar.getInstance().getTime());
+ }
+ catch (ParseException e) {
+ return false;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c396e94a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/support/DefaultIgnoreCondition.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/support/DefaultIgnoreCondition.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/support/DefaultIgnoreCondition.java
new file mode 100755
index 0000000..24cd98a
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/support/DefaultIgnoreCondition.java
@@ -0,0 +1,41 @@
+package com.gemstone.gemfire.test.junit.support;
+
+import org.junit.runner.Description;
+import com.gemstone.gemfire.test.junit.IgnoreCondition;
+
+/**
+ * The DefaultIgnoreCondition class...
+ *
+ * @author John Blum
+ * @see org.junit.runner.Description
+ * @see com.gemstone.gemfire.test.junit.ConditionalIgnore
+ * @see com.gemstone.gemfire.test.junit.IgnoreCondition
+ */
+@SuppressWarnings("unused")
+public class DefaultIgnoreCondition implements IgnoreCondition {
+
+ public static final boolean DEFAULT_IGNORE = false;
+
+ public static final DefaultIgnoreCondition DO_NOT_IGNORE = new DefaultIgnoreCondition(false);
+ public static final DefaultIgnoreCondition IGNORE = new DefaultIgnoreCondition(true);
+
+ private final boolean ignore;
+
+ public DefaultIgnoreCondition() {
+ this(DEFAULT_IGNORE);
+ }
+
+ public DefaultIgnoreCondition(final boolean ignore) {
+ this.ignore = ignore;
+ }
+
+ public boolean isIgnore() {
+ return ignore;
+ }
+
+ @Override
+ public boolean evaluate(final Description testCaseDescription) {
+ return isIgnore();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/c396e94a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/support/IgnoreConditionEvaluationException.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/support/IgnoreConditionEvaluationException.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/support/IgnoreConditionEvaluationException.java
new file mode 100755
index 0000000..50e1bc7
--- /dev/null
+++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/support/IgnoreConditionEvaluationException.java
@@ -0,0 +1,27 @@
+package com.gemstone.gemfire.test.junit.support;
+
+/**
+ * The IgnoreConditionEvaluationException class...
+ *
+ * @author John Blum
+ * @see java.lang.RuntimeException
+ */
+@SuppressWarnings("unused")
+public class IgnoreConditionEvaluationException extends RuntimeException {
+
+ public IgnoreConditionEvaluationException() {
+ }
+
+ public IgnoreConditionEvaluationException(final String message) {
+ super(message);
+ }
+
+ public IgnoreConditionEvaluationException(final Throwable cause) {
+ super(cause);
+ }
+
+ public IgnoreConditionEvaluationException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+
+}
[4/9] incubator-geode git commit: Dunit changes for JUnit 4 syntax.
Refactoring to modernize API.
Posted by kl...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ExpectedExceptionString.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ExpectedExceptionString.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ExpectedExceptionString.java
new file mode 100755
index 0000000..a1ef782
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ExpectedExceptionString.java
@@ -0,0 +1,142 @@
+package com.gemstone.gemfire.test.dunit;
+
+import static com.gemstone.gemfire.test.dunit.Invoke.invokeInEveryVM;
+
+import java.io.Serializable;
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+import org.apache.logging.log4j.Logger;
+
+import com.gemstone.gemfire.internal.logging.LogService;
+
+/**
+ * An expected exception string which is added or removed in the log to
+ * suppress it during greplogs (grep for error strings).
+ *
+ * Extracted from DistributedTestCase. Renamed from ExpectedException to
+ * prevent conflict with the JUnit rule. Note that the implementation
+ * is still writing <code><ExpectedException ...></code> statements to the
+ * log for the <code>batterytest.greplogs.LogConsumer</code>.
+ *
+ * @author Mitch Thomas
+ * @since 5.7bugfix
+ * @see batterytest.greplogs.LogConsumer
+ */
+public class ExpectedExceptionString implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private static final Logger logger = LogService.getLogger();
+
+ // Note: if you change these prefixes and suffix then you must also change batterytest.greplogs.LogConsumer to match
+ private static final String LOG_MESSAGE_PREFIX_ADD = "<ExpectedException action=add>";
+ private static final String LOG_MESSAGE_PREFIX_REMOVE = "<ExpectedException action=remove>";
+ private static final String LOG_MESSAGE_SUFFIX = "</ExpectedException>";
+
+ private final String exceptionString;
+
+ private final transient VM vm;
+
+ // TODO: prevent memory leak here
+ private static final Queue<ExpectedExceptionString> expectedExceptionStrings = new ConcurrentLinkedQueue<ExpectedExceptionString>();
+
+ public ExpectedExceptionString(final String exceptionString) {
+ this(exceptionString, null);
+ }
+
+ public ExpectedExceptionString(final String exceptionString, final VM vm) {
+ this.exceptionString = exceptionString;
+ this.vm = vm;
+ }
+
+ public String getAddMessage() {
+ return LOG_MESSAGE_PREFIX_ADD + this.exceptionString + LOG_MESSAGE_SUFFIX;
+ }
+
+ public String getRemoveMessage() {
+ return LOG_MESSAGE_PREFIX_REMOVE + this.exceptionString + LOG_MESSAGE_SUFFIX;
+ }
+
+ public void remove() {
+ final SerializableRunnable removeRunnable = newRemoveSerializableRunnable(getRemoveMessage());
+
+ if (this.vm != null) {
+ this.vm.invoke(removeRunnable);
+ } else {
+ invokeInEveryVM(removeRunnable);
+ }
+
+ logger.info(getRemoveMessage());
+ }
+
+ /**
+ * Log in all VMs the expected exception string to prevent grep logs from
+ * complaining. The expected string is used by the GrepLogs utility and so
+ * can contain regular expression characters.
+ *
+ * If you do not remove the expected exception, it will be removed at the
+ * end of your test case automatically.
+ *
+ * @since 5.7bugfix
+ * @param exception the exception string to expect
+ * @return an instance that a test can use for removal
+ */
+ public static ExpectedExceptionString addExpectedExceptionString(final String exception) {
+ return addExpectedExceptionString(exception, null);
+ }
+
+ /**
+ * Log in all VMs, the
+ * expected exception string to prevent grep logs from complaining. The
+ * expected string is used by the GrepLogs utility and so can contain
+ * regular expression characters.
+ *
+ * @since 5.7bugfix
+ * @param exceptionString the exception string to expect
+ * @param vm the VM on which to log the expected exception or null for all VMs
+ * @return an instance that a test can use for removal
+ */
+ public static ExpectedExceptionString addExpectedExceptionString(final String exceptionString, final VM vm) {
+ final ExpectedExceptionString expectedOutput;
+ if (vm != null) {
+ expectedOutput = new ExpectedExceptionString(exceptionString, vm);
+ } else {
+ expectedOutput = new ExpectedExceptionString(exceptionString);
+ }
+
+ final String addMessage = expectedOutput.getAddMessage();
+
+ final SerializableRunnable addRunnable = newAddSerializableRunnable(addMessage);
+
+ if (vm != null) {
+ vm.invoke(addRunnable);
+ } else {
+ invokeInEveryVM(addRunnable);
+ }
+
+ logger.info(addMessage);
+ expectedExceptionStrings.add(expectedOutput);
+ return expectedOutput;
+ }
+
+ static ExpectedExceptionString poll() {
+ return expectedExceptionStrings.poll();
+ }
+
+ @SuppressWarnings("serial")
+ private static SerializableRunnable newAddSerializableRunnable(final String addMessage) {
+ return new SerializableRunnable("addExpectedExceptionString") {
+ public void run() {
+ logger.info(addMessage);
+ }
+ };
+ }
+
+ @SuppressWarnings("serial")
+ private static SerializableRunnable newRemoveSerializableRunnable(final String removeMessage) {
+ return new SerializableRunnable("removeExpectedExceptionString") {
+ public void run() {
+ logger.info(removeMessage);
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Host.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Host.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Host.java
new file mode 100644
index 0000000..6d69436
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Host.java
@@ -0,0 +1,201 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * <P>This class represents a host on which a remote method may be
+ * invoked. It provides access to the VMs and GemFire systems that
+ * run on that host.</P>
+ *
+ * <P>Additionally, it provides access to the Java RMI registry that
+ * runs on the host. By default, an RMI registry is only started on
+ * the host on which Hydra's Master VM runs. RMI registries may be
+ * started on other hosts via additional Hydra configuration.</P>
+ *
+ * @author David Whitlock
+ *
+ */
+public abstract class Host implements java.io.Serializable {
+
+ /** The available hosts */
+ protected static List hosts = new ArrayList();
+
+ private static VM locator;
+
+ /** Indicates an unstarted RMI registry */
+ protected static int NO_REGISTRY = -1;
+
+ //////////////////// Instance Fields ////////////////////
+
+ /** The name of this host machine */
+ private String hostName;
+
+ /** The VMs that run on this host */
+ private List vms;
+
+ /** The GemFire systems that are available on this host */
+ private List systems;
+
+ /** Key is system name, value is GemFireSystem instance */
+ private HashMap systemNames;
+
+ //////////////////// Static Methods /////////////////////
+
+ /**
+ * Returns the number of known hosts
+ */
+ public static int getHostCount() {
+ return hosts.size();
+ }
+
+ /**
+ * Makes note of a new <code>Host</code>
+ */
+ protected static void addHost(Host host) {
+ hosts.add(host);
+ }
+
+ /**
+ * Returns a given host
+ *
+ * @param n
+ * A zero-based identifier of the host
+ *
+ * @throws IllegalArgumentException
+ * <code>n</code> is more than the number of hosts
+ */
+ public static Host getHost(int n) {
+ int size = hosts.size();
+ if (n >= size) {
+ String s = "Cannot request host " + n + ". There are only " +
+ size + " hosts.";
+ throw new IllegalArgumentException(s);
+
+ } else {
+ return (Host) hosts.get(n);
+ }
+ }
+
+ ///////////////////// Constructors //////////////////////
+
+ /**
+ * Creates a new <code>Host</code> with the given name
+ */
+ protected Host(String hostName) {
+ if (hostName == null) {
+ String s = "Cannot create a Host with a null name";
+ throw new NullPointerException(s);
+ }
+
+ this.hostName = hostName;
+ this.vms = new ArrayList();
+ this.systems = new ArrayList();
+ this.systemNames = new HashMap();
+ }
+
+ //////////////////// Instance Methods ////////////////////
+
+ /**
+ * Returns the machine name of this host
+ */
+ public String getHostName() {
+ return this.hostName;
+ }
+
+ /**
+ * Returns the number of VMs that run on this host
+ */
+ public int getVMCount() {
+ return this.vms.size();
+ }
+
+ /**
+ * Returns a VM that runs on this host
+ *
+ * @param n
+ * A zero-based identifier of the VM
+ *
+ * @throws IllegalArgumentException
+ * <code>n</code> is more than the number of VMs
+ */
+ public VM getVM(int n) {
+ int size = vms.size();
+ if (n >= size) {
+ String s = "Cannot request VM " + n + ". There are only " +
+ size + " VMs on " + this;
+ throw new IllegalArgumentException(s);
+
+ } else {
+ return (VM) vms.get(n);
+ }
+ }
+
+ /**
+ * Adds a VM to this <code>Host</code> with the given process id and client record.
+ */
+ protected void addVM(int pid, RemoteDUnitVMIF client) {
+ VM vm = new VM(this, pid, client);
+ this.vms.add(vm);
+ }
+
+ public static VM getLocator() {
+ return locator;
+ }
+
+ private static void setLocator(VM l) {
+ locator = l;
+ }
+
+ protected void addLocator(int pid, RemoteDUnitVMIF client) {
+ setLocator(new VM(this, pid, client));
+ }
+
+ /**
+ * Returns the number of GemFire systems that run on this host
+ */
+ public int getSystemCount() {
+ return this.systems.size();
+ }
+
+ //////////////////// Utility Methods ////////////////////
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer("Host ");
+ sb.append(this.getHostName());
+ sb.append(" with ");
+ sb.append(getVMCount());
+ sb.append(" VMs");
+ return sb.toString();
+ }
+
+ /**
+ * Two <code>Host</code>s are considered equal if they have the same
+ * name.
+ */
+ public boolean equals(Object o) {
+ if (o instanceof Host) {
+ return ((Host) o).getHostName().equals(this.getHostName());
+
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * A <code>Host</code>'s hash code is based on the hash code of its
+ * name.
+ */
+ public int hashCode() {
+ return this.getHostName().hashCode();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
new file mode 100755
index 0000000..bd9eaf6
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
@@ -0,0 +1,146 @@
+package com.gemstone.gemfire.test.dunit;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A set of remote invocation methods useful for writing tests.
+ * <pr/>
+ * These methods can be used directly:
+ * <code>Invoke.invokeInEveryVM(...)</code>, however, they read better if they
+ * are referenced through static import:
+ *
+ * <pre>
+ * import static com.gemstone.gemfire.test.dunit.Invoke.*;
+ * ...
+ * invokeInEveryVM(...);
+ * </pre>
+ * <pr/>
+ * Extracted from DistributedTestCase
+ *
+ * @see VM
+ * @see SerializableCallable
+ * @see SerializableRunnable
+ * @see RepeatableRunnable
+ */
+public class Invoke {
+
+ protected Invoke() {
+ }
+
+ /**
+ * Invokes a <code>SerializableRunnable</code> in every VM that DUnit knows about.
+ *
+ * @see VM#invoke(Runnable)
+ */
+ public static void invokeInEveryVM(final SerializableRunnable work) {
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ vm.invoke(work);
+ }
+ }
+ }
+
+ public static void invokeInLocator(final SerializableRunnable work) {
+ Host.getLocator().invoke(work);
+ }
+
+ /**
+ * Invokes a <code>SerializableCallable</code> in every VM that DUnit knows about.
+ *
+ * @return a Map of results, where the key is the VM and the value is the result for that VM
+ * @see VM#invoke(java.util.concurrent.Callable)
+ */
+ public static Map<VM, Object> invokeInEveryVM(final SerializableCallable<?> work) {
+ final Map<VM, Object> results = new HashMap<VM, Object>();
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ results.put(vm, vm.invoke(work));
+ }
+ }
+ return results;
+ }
+
+ /**
+ * Invokes a method in every remote VM that DUnit knows about.
+ *
+ * @see VM#invoke(Class, String)
+ */
+ public static void invokeInEveryVM(final Class<?> theClass, final String methodName) {
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ vm.invoke(theClass, methodName);
+ }
+ }
+ }
+
+ /**
+ * Invokes a method in every remote VM that DUnit knows about.
+ *
+ * @see VM#invoke(Class, String)
+ */
+ public static void invokeInEveryVM(final Class<?> theClass, final String methodName, final Object[] methodArgs) {
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ vm.invoke(theClass, methodName, methodArgs);
+ }
+ }
+ }
+
+ public static void invokeRepeatingIfNecessary(final VM vm, final RepeatableRunnable task) {
+ vm.invokeRepeatingIfNecessary(task, 0);
+ }
+
+ /**
+ * For ACK scopes, no repeat should be necessary.
+ *
+ * @param vm
+ * @param task
+ * @param repeatTimeoutMs the number of milliseconds to try repeating validation code in the
+ * event that AssertionFailedError is thrown.
+ */
+ public static void invokeRepeatingIfNecessary(final VM vm, final RepeatableRunnable task, final long repeatTimeoutMs) {
+ vm.invokeRepeatingIfNecessary(task, repeatTimeoutMs);
+ }
+
+ /**
+ * Invokes a <code>SerializableRunnable</code> in every VM that
+ * DUnit knows about. If work.run() throws an assertion failure,
+ * its execution is repeated, until no assertion failure occurs or
+ * repeatTimeout milliseconds have passed.
+ *
+ * @see VM#invoke(Runnable)
+ */
+ public static void invokeInEveryVMRepeatingIfNecessary(final RepeatableRunnable work) {
+ invokeInEveryVMRepeatingIfNecessary(work, 0);
+ }
+
+ public static void invokeInEveryVMRepeatingIfNecessary(final RepeatableRunnable work, final long repeatTimeoutMs) {
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ for (int v = 0; v < host.getVMCount(); v++) {
+ VM vm = host.getVM(v);
+ vm.invokeRepeatingIfNecessary(work, repeatTimeoutMs);
+ }
+ }
+ }
+
+ /** Return the total number of VMs on all hosts */
+ public static int getVMCount() {
+ int count = 0;
+ for (int h = 0; h < Host.getHostCount(); h++) {
+ Host host = Host.getHost(h);
+ count += host.getVMCount();
+ }
+ return count;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
new file mode 100755
index 0000000..446b4bf
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
@@ -0,0 +1,70 @@
+package com.gemstone.gemfire.test.dunit;
+
+import java.util.Random;
+
+/**
+ * Extracted from DistributedTestCase
+ */
+public class Jitter {
+
+ /**
+ * If true, we randomize the amount of time we wait
+ */
+ private static final boolean USE_JITTER = true;
+
+ private static final Random jitter = new Random();
+
+ protected Jitter() {
+ }
+
+ /**
+ * Returns an adjusted interval from <code>minimum()</code to
+ * <code>intervalMillis</code> milliseconds. If jittering is disabled then
+ * the value returned will be equal to intervalMillis.
+ *
+ * @param intervalMillis
+ * @return adjust milliseconds to use as interval for WaitCriteria polling
+ */
+ static long jitterInterval(final long intervalMillis) {
+ if (USE_JITTER) {
+ return adjustIntervalIfJitterIsEnabled(intervalMillis);
+ } else {
+ return intervalMillis;
+ }
+ }
+
+ static int minimum() {
+ return 10;
+ }
+
+ static int maximum() {
+ return 5000;
+ }
+
+ /**
+ * If jittering is enabled then returns a jittered interval up to a maximum
+ * of <code>intervalMillis</code> milliseconds, inclusive.
+ *
+ * If jittering is disabled then returns <code>intervalMillis</code>.
+ *
+ * The result is bounded by 50 ms as a minimum and 5000 ms as a maximum.
+ *
+ * @param ms total amount of time to wait
+ * @return randomized interval we should wait
+ */
+ private static int adjustIntervalIfJitterIsEnabled(final long intervalMillis) {
+ final int minLegal = minimum();
+ final int maxLegal = maximum();
+
+ if (intervalMillis <= minLegal) {
+ return (int)intervalMillis; // Don't ever jitter anything below this.
+ }
+
+ int maxValue = maxLegal;
+ if (intervalMillis < maxLegal) {
+ maxValue = (int)intervalMillis;
+ }
+
+ return minLegal + jitter.nextInt(maxValue - minLegal + 1);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RMIException.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RMIException.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RMIException.java
new file mode 100644
index 0000000..d08ac25
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RMIException.java
@@ -0,0 +1,161 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import com.gemstone.gemfire.GemFireException;
+
+/**
+ * This exception is thrown when an exception occurs during a remote
+ * method invocation. This {@link RuntimeException} wraps the actual
+ * exception. It allows distributed unit tests to verify that an
+ * exception was thrown in a different VM.
+ *
+ * <PRE>
+ * VM vm0 = host0.getVM(0);
+ * try {
+ * vm.invoke(this.getClass(), "getUnknownObject");
+ *
+ * } catch (RMIException ex) {
+ * assertEquals(ex.getCause() instanceof ObjectException);
+ * }
+ * </PRE>
+ *
+ * Note that special steps are taken so that the stack trace of the
+ * cause exception reflects the call stack on the remote machine.
+ * The stack trace of the exception returned by {@link #getCause()}
+ * may not be available.
+ *
+ * @see hydra.RemoteTestModuleIF
+ *
+ * @author David Whitlock
+ *
+ */
+public class RMIException extends GemFireException {
+
+ /** SHADOWED FIELD that holds the cause exception (as opposed to the
+ * HokeyException */
+ private Throwable cause;
+
+ /** The name of the method being invoked */
+ private String methodName;
+
+ /** The name of the class (or class of the object type) whose method
+ * was being invoked */
+ private String className;
+
+ /** The type of exception that was thrown in the remote VM */
+ private String exceptionClassName;
+
+ /** Stack trace for the exception that was thrown in the remote VM */
+ private String stackTrace;
+
+ /** The VM in which the method was executing */
+ private VM vm;
+
+ //////////////////////// Constructors ////////////////////////
+
+ /**
+ * Creates a new <code>RMIException</code> that was caused by a
+ * given <code>Throwable</code> while invoking a given method.
+ */
+ public RMIException(VM vm, String className, String methodName,
+ Throwable cause) {
+ super("While invoking " + className + "." + methodName + " in " +
+ vm, cause);
+ this.cause = cause;
+ this.className = className;
+ this.methodName = methodName;
+ this.vm = vm;
+ }
+
+ /**
+ * Creates a new <code>RMIException</code> to indicate that an
+ * exception of a given type was thrown while invoking a given
+ * method.
+ *
+ * @param vm
+ * The VM in which the method was executing
+ * @param className
+ * The name of the class whose method was being invoked
+ * remotely
+ * @param methodName
+ * The name of the method that was being invoked remotely
+ * @param cause
+ * The type of exception that was thrown in the remote VM
+ * @param stackTrace
+ * The stack trace of the exception from the remote VM
+ */
+ public RMIException(VM vm, String className, String methodName,
+ Throwable cause, String stackTrace) {
+ super("While invoking " + className + "." + methodName + " in " +
+ vm, new HokeyException(cause, stackTrace));
+ this.vm = vm;
+ this.cause = cause;
+ this.className = className;
+ this.methodName = methodName;
+// this.exceptionClassName = exceptionClassName; assignment has no effect
+ this.stackTrace = stackTrace;
+ }
+
+ /**
+ * Returns the class name of the exception that was thrown in a
+ * remote method invocation.
+ */
+ public String getExceptionClassName() {
+ return this.exceptionClassName;
+ }
+
+// /**
+// * Returns the stack trace for the exception that was thrown in a
+// * remote method invocation.
+// */
+// public String getStackTrace() {
+// return this.stackTrace;
+// }
+
+ /**
+ * Returns the cause of this exception. Note that this is not
+ * necessarily the exception that gets printed out with the stack
+ * trace.
+ */
+ public Throwable getCause() {
+ return this.cause;
+ }
+
+ /**
+ * Returns the VM in which the remote method was invoked
+ */
+ public VM getVM() {
+ return this.vm;
+ }
+
+ ////////////////////// Inner Classes //////////////////////
+
+ /**
+ * A hokey exception class that makes it looks like we have a real
+ * cause exception.
+ */
+ private static class HokeyException extends Throwable {
+ private String stackTrace;
+ private String toString;
+
+ HokeyException(Throwable cause, String stackTrace) {
+ this.toString = cause.toString();
+ this.stackTrace = stackTrace;
+ }
+
+ public void printStackTrace(java.io.PrintWriter pw) {
+ pw.print(this.stackTrace);
+ pw.flush();
+ }
+
+ public String toString() {
+ return this.toString;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RemoteDUnitVMIF.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RemoteDUnitVMIF.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RemoteDUnitVMIF.java
new file mode 100644
index 0000000..412aeac
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RemoteDUnitVMIF.java
@@ -0,0 +1,18 @@
+package com.gemstone.gemfire.test.dunit;
+
+import hydra.MethExecutorResult;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface RemoteDUnitVMIF extends Remote {
+
+ MethExecutorResult executeMethodOnObject(Object o, String methodName) throws RemoteException;
+
+ MethExecutorResult executeMethodOnObject(Object o, String methodName,
+ Object[] args) throws RemoteException;
+
+ MethExecutorResult executeMethodOnClass(String name, String methodName,
+ Object[] args) throws RemoteException;
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RepeatableRunnable.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RepeatableRunnable.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RepeatableRunnable.java
new file mode 100644
index 0000000..c8952bb
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/RepeatableRunnable.java
@@ -0,0 +1,13 @@
+package com.gemstone.gemfire.test.dunit;
+
+/**
+ * A RepeatableRunnable is an object that implements a method that
+ * can be invoked repeatably without causing any side affects.
+ *
+ * @author dmonnie
+ */
+public interface RepeatableRunnable {
+
+ public void runRepeatingIfNecessary(long repeatTimeoutMs);
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableCallable.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableCallable.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableCallable.java
new file mode 100644
index 0000000..2c21284
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableCallable.java
@@ -0,0 +1,61 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import java.io.Serializable;
+import java.util.concurrent.Callable;
+
+/**
+ * This interface provides both {@link Serializable} and {@link
+ * Callable}. It is often used in conjunction with {@link
+ * VM#invoke(Callable)}.
+ *
+ * <PRE>
+ * public void testRepilcatedRegionPut() {
+ * final Host host = Host.getHost(0);
+ * VM vm0 = host.getVM(0);
+ * VM vm1 = host.getVM(1);
+ * final String name = this.getUniqueName();
+ * final Object value = new Integer(42);
+ *
+ * SerializableCallable putMethod = new SerializableCallable("Replicated put") {
+ * public Object call() throws Exception {
+ * ...// get replicated test region //...
+ * return region.put(name, value);
+ * }
+ * });
+ * assertNull(vm0.invoke(putMethod));
+ * assertEquals(value, vm1.invoke(putMethod));
+ * }
+ * </PRE>
+ *
+ * @author Mitch Thomas
+ */
+public abstract class SerializableCallable<T> implements Callable<T>, Serializable {
+
+ private static final long serialVersionUID = -5914706166172952484L;
+
+ private String name;
+
+ public SerializableCallable() {
+ this.name = null;
+ }
+
+ public SerializableCallable(String name) {
+ this.name = name;
+ }
+
+ public String toString() {
+ if (this.name != null) {
+ return "\"" + this.name + "\"";
+
+ } else {
+ return super.toString();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
new file mode 100644
index 0000000..28eabc3
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
@@ -0,0 +1,83 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import java.io.Serializable;
+
+/**
+ * This interface provides both {@link Serializable} and {@link
+ * Runnable}. It is often used in conjunction with {@link
+ * VM#invoke(Runnable)}.
+ *
+ * <PRE>
+ * public void testRegionPutGet() {
+ * final Host host = Host.getHost(0);
+ * VM vm0 = host.getVM(0);
+ * VM vm1 = host.getVM(1);
+ * final String name = this.getUniqueName();
+ * final Object value = new Integer(42);
+ *
+ * vm0.invoke(new SerializableRunnable("Put value") {
+ * public void run() {
+ * ...// get the region //...
+ * region.put(name, value);
+ * }
+ * });
+ * vm1.invoke(new SerializableRunnable("Get value") {
+ * public void run() {
+ * ...// get the region //...
+ * assertEquals(value, region.get(name));
+ * }
+ * });
+ * }
+ * </PRE>
+ */
+public abstract class SerializableRunnable
+ implements Serializable, Runnable {
+
+ private static final long serialVersionUID = 7584289978241650456L;
+
+ private String name;
+
+ public SerializableRunnable() {
+ this.name = null;
+ }
+
+ /**
+ * This constructor lets you do the following:
+ *
+ * <PRE>
+ * vm.invoke(new SerializableRunnable("Do some work") {
+ * public void run() {
+ * // ...
+ * }
+ * });
+ * </PRE>
+ */
+ public SerializableRunnable(String name) {
+ this.name = name;
+ }
+
+ public void setName(String newName) {
+ this.name = newName;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public String toString() {
+ if (this.name != null) {
+ return "\"" + this.name + "\"";
+
+ } else {
+ return super.toString();
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/StoppableWaitCriterion.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/StoppableWaitCriterion.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/StoppableWaitCriterion.java
new file mode 100755
index 0000000..b1e0d88
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/StoppableWaitCriterion.java
@@ -0,0 +1,12 @@
+package com.gemstone.gemfire.test.dunit;
+
+/**
+ * Extracted from DistributedTestCase
+ */
+public interface StoppableWaitCriterion extends WaitCriterion {
+ /**
+ * If this method returns true then quit waiting even if we are not done.
+ * This allows a wait to fail early.
+ */
+ public boolean stopWaiting();
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ThreadDump.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ThreadDump.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ThreadDump.java
new file mode 100755
index 0000000..acf43b9
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ThreadDump.java
@@ -0,0 +1,157 @@
+package com.gemstone.gemfire.test.dunit;
+
+import static com.gemstone.gemfire.test.dunit.Jitter.*;
+import static org.junit.Assert.fail;
+
+import com.gemstone.gemfire.LogWriter;
+import com.gemstone.gemfire.internal.OSProcess;
+import com.gemstone.gemfire.internal.logging.LocalLogWriter;
+import com.gemstone.gemfire.internal.logging.LogWriterImpl;
+
+/**
+ * A set of thread dump methods useful for writing tests.
+ * <pr/>
+ * These methods can be used directly:
+ * <code>ThreadDump.dumpStack(...)</code>, however, they read better if they
+ * are referenced through static import:
+ *
+ * <pre>
+ * import static com.gemstone.gemfire.test.dunit.ThreadDump.*;
+ * ...
+ * dumpStack(...);
+ * </pre>
+ * <pr/>
+ * Extracted from DistributedTestCase
+ *
+ * @see VM
+ * @see Host
+ */
+@SuppressWarnings("serial")
+public class ThreadDump {
+
+ protected ThreadDump() {
+ }
+
+ /**
+ * Print a stack dump for this vm
+ *
+ * @author bruce
+ * @since 5.0
+ */
+ public static void dumpStack() {
+ com.gemstone.gemfire.internal.OSProcess.printStacks(0, false);
+ }
+
+ /**
+ * Print a stack dump for the given vm
+ *
+ * @author bruce
+ * @since 5.0
+ */
+ public static void dumpStack(final VM vm) {
+ vm.invoke(dumpStackSerializableRunnable());
+ }
+
+ /**
+ * Print stack dumps for all vms on the given host
+ *
+ * @author bruce
+ * @since 5.0
+ */
+ public static void dumpStack(final Host host) {
+ for (int v=0; v < host.getVMCount(); v++) {
+ host.getVM(v).invoke(dumpStackSerializableRunnable());
+ }
+ }
+
+ /**
+ * Print stack dumps for all vms on all hosts
+ *
+ * @author bruce
+ * @since 5.0
+ */
+ public static void dumpAllStacks() {
+ for (int h=0; h < Host.getHostCount(); h++) {
+ dumpStack(Host.getHost(h));
+ }
+ }
+
+ public static void dumpStackTrace(final Thread thread, final StackTraceElement[] stack, final LogWriter logWriter) { // TODO: remove LogWriter
+ StringBuilder msg = new StringBuilder();
+ msg.append("Thread=<")
+ .append(thread)
+ .append("> stackDump:\n");
+ for (int i=0; i < stack.length; i++) {
+ msg.append("\t")
+ .append(stack[i])
+ .append("\n");
+ }
+ logWriter.info(msg.toString());
+ }
+
+ /**
+ * Dump all thread stacks
+ */
+ public static void dumpMyThreads(final LogWriter logWriter) { // TODO: remove LogWriter
+ OSProcess.printStacks(0, false);
+ }
+
+ /**
+ * Wait for a thread to join
+ * @param t thread to wait on
+ * @param ms maximum time to wait
+ * @throws AssertionFailure if the thread does not terminate
+ */
+ static public void join(Thread t, long ms, LogWriter logger) {
+ final long tilt = System.currentTimeMillis() + ms;
+ final long incrementalWait = jitterInterval(ms);
+ final long start = System.currentTimeMillis();
+ for (;;) {
+ // I really do *not* understand why this check is necessary
+ // but it is, at least with JDK 1.6. According to the source code
+ // and the javadocs, one would think that join() would exit immediately
+ // if the thread is dead. However, I can tell you from experimentation
+ // that this is not the case. :-( djp 2008-12-08
+ if (!t.isAlive()) {
+ break;
+ }
+ try {
+ t.join(incrementalWait);
+ } catch (InterruptedException e) {
+ fail("interrupted");
+ }
+ if (System.currentTimeMillis() >= tilt) {
+ break;
+ }
+ } // for
+ if (logger == null) {
+ logger = new LocalLogWriter(LogWriterImpl.INFO_LEVEL, System.out);
+ }
+ if (t.isAlive()) {
+ logger.info("HUNG THREAD");
+ dumpStackTrace(t, t.getStackTrace(), logger);
+ dumpMyThreads(logger);
+ t.interrupt(); // We're in trouble!
+ fail("Thread did not terminate after " + ms + " ms: " + t);
+// getLogWriter().warning("Thread did not terminate"
+// /* , new Exception()*/
+// );
+ }
+ long elapsedMs = (System.currentTimeMillis() - start);
+ if (elapsedMs > 0) {
+ String msg = "Thread " + t + " took "
+ + elapsedMs
+ + " ms to exit.";
+ logger.info(msg);
+ }
+ }
+
+ private static SerializableRunnable dumpStackSerializableRunnable() {
+ return new SerializableRunnable() {
+ @Override
+ public void run() {
+ dumpStack();
+ }
+ };
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/VM.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/VM.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/VM.java
new file mode 100644
index 0000000..f850184
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/VM.java
@@ -0,0 +1,1333 @@
+/*=========================================================================
+ * Copyright (c) 2010-2014 Pivotal Software, Inc. All Rights Reserved.
+ * This product is protected by U.S. and international copyright
+ * and intellectual property laws. Pivotal products are covered by
+ * one or more patents listed at http://www.pivotal.io/patents.
+ *=========================================================================
+ */
+package com.gemstone.gemfire.test.dunit;
+
+import hydra.MethExecutorResult;
+
+import java.io.File;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.rmi.RemoteException;
+import java.util.concurrent.Callable;
+
+/**
+ * This class represents a Java Virtual Machine that runs on a host.
+ *
+ * @author David Whitlock
+ *
+ */
+public class VM implements java.io.Serializable {
+
+ /** The host on which this VM runs */
+ private Host host;
+
+ /** The process id of this VM */
+ private int pid;
+
+ /** The hydra client for this VM */
+ private RemoteDUnitVMIF client;
+
+ /** The state of this VM */
+ private volatile boolean available;
+
+ //////////////////// Constructors ////////////////////
+
+ /**
+ * Creates a new <code>VM</code> that runs on a given host with a
+ * given process id.
+ */
+ public VM(Host host, int pid, RemoteDUnitVMIF client) {
+ this.host = host;
+ this.pid = pid;
+ this.client = client;
+ this.available = true;
+ }
+
+ ////////////////////// Accessors //////////////////////
+
+ /**
+ * Returns the host on which this <code>VM</code> runs
+ */
+ public Host getHost() {
+ return this.host;
+ }
+
+ /**
+ * Returns the process id of this <code>VM</code>
+ */
+ public int getPid() {
+ return this.pid;
+ }
+
+ ///////////////// Remote Method Invocation ///////////////
+
+ /**
+ * Invokes a static zero-arg method with an {@link Object} or
+ * <code>void</code> return type in this VM. If the return type of
+ * the method is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public Object invoke(Class c, String methodName) {
+ return invoke(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Asynchronously invokes a static zero-arg method with an {@link
+ * Object} or <code>void</code> return type in this VM. If the
+ * return type of the method is <code>void</code>, <code>null</code>
+ * is returned.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ */
+ public AsyncInvocation invokeAsync(Class c, String methodName) {
+ return invokeAsync(c, methodName, null);
+ }
+
+ /**
+ * Invokes a static method with an {@link Object} or
+ * <code>void</code> return type in this VM. If the return type of
+ * the method is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public Object invoke(Class c, String methodName, Object[] args) {
+ if (!this.available) {
+ String s = "VM not available: " + this;
+ throw new RMIException(this, c.getName(), methodName,
+ new IllegalStateException(s));
+ }
+ MethExecutorResult result = null;
+ int retryCount = 120;
+ do {
+ try {
+ result = this.client.executeMethodOnClass(c.getName(), methodName, args);
+ break; // out of while loop
+ } catch( RemoteException e ) {
+ boolean isWindows = false;
+ String os = System.getProperty("os.name");
+ if (os != null) {
+ if (os.indexOf("Windows") != -1) {
+ isWindows = true;
+ }
+ }
+ if (isWindows && retryCount-- > 0) {
+ boolean interrupted = Thread.interrupted();
+ try { Thread.sleep(1000); } catch (InterruptedException ignore) {interrupted = true;}
+ finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ } else {
+ throw new RMIException(this, c.getName(), methodName, e );
+ }
+ }
+ } while (true);
+
+ if (!result.exceptionOccurred()) {
+ return result.getResult();
+
+ } else {
+ Throwable thr = result.getException();
+ throw new RMIException(this, c.getName(), methodName, thr,
+ result.getStackTrace());
+ }
+ }
+
+ /**
+ * Asynchronously invokes a static method with an {@link Object} or
+ * <code>void</code> return type in this VM. If the return type of
+ * the method is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ */
+ public AsyncInvocation invokeAsync(final Class c,
+ final String methodName,
+ final Object[] args) {
+ AsyncInvocation ai =
+ new AsyncInvocation(c, methodName, new Runnable() {
+ public void run() {
+ final Object o = invoke(c, methodName, args);
+ AsyncInvocation.setReturnValue(o);
+ }
+ });
+ ai.start();
+ return ai;
+ }
+
+ /**
+ * Asynchronously invokes an instance method with an {@link Object} or
+ * <code>void</code> return type in this VM. If the return type of
+ * the method is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param o
+ * The object on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ */
+ public AsyncInvocation invokeAsync(final Object o,
+ final String methodName,
+ final Object[] args) {
+ AsyncInvocation ai =
+ new AsyncInvocation(o, methodName, new Runnable() {
+ public void run() {
+ final Object ret = invoke(o, methodName, args);
+ AsyncInvocation.setReturnValue(ret);
+ }
+ });
+ ai.start();
+ return ai;
+ }
+
+ /**
+ * Invokes the <code>run</code> method of a {@link Runnable} in this
+ * VM. Recall that <code>run</code> takes no arguments and has no
+ * return value.
+ *
+ * @param r
+ * The <code>Runnable</code> to be run
+ *
+ * @see SerializableRunnable
+ */
+ public AsyncInvocation invokeAsync(Runnable r) {
+ return invokeAsync(r, "run", new Object[0]);
+ }
+
+ /**
+ * Invokes the <code>call</code> method of a {@link Runnable} in this
+ * VM.
+ *
+ * @param c
+ * The <code>Callable</code> to be run
+ *
+ * @see SerializableCallable
+ */
+ public AsyncInvocation invokeAsync(Callable c) {
+ return invokeAsync(c, "call", new Object[0]);
+ }
+
+ /**
+ * Invokes the <code>run</code> method of a {@link Runnable} in this
+ * VM. Recall that <code>run</code> takes no arguments and has no
+ * return value.
+ *
+ * @param r
+ * The <code>Runnable</code> to be run
+ *
+ * @see SerializableRunnable
+ */
+ public void invoke(Runnable r) {
+ invoke(r, "run");
+ }
+
+ /**
+ * Invokes the <code>run</code> method of a {@link Runnable} in this
+ * VM. Recall that <code>run</code> takes no arguments and has no
+ * return value.
+ *
+ * @param c
+ * The <code>Callable</code> to be run
+ *
+ * @see SerializableCallable
+ */
+ public Object invoke(Callable c) {
+ return invoke(c, "call");
+ }
+
+ /**
+ * Invokes the <code>run</code method of a {@link Runnable} in this
+ * VM. If the invocation throws AssertionFailedError, and repeatTimeoutMs
+ * is >0, the <code>run</code> method is invoked repeatedly until it
+ * either succeeds, or repeatTimeoutMs has passed. The AssertionFailedError
+ * is thrown back to the sender of this method if <code>run</code> has not
+ * completed successfully before repeatTimeoutMs has passed.
+ */
+ public void invokeRepeatingIfNecessary(RepeatableRunnable o, long repeatTimeoutMs) {
+ invoke(o, "runRepeatingIfNecessary", new Object[] {new Long(repeatTimeoutMs)});
+ }
+
+ /**
+ * Invokes an instance method with no arguments on an object that is
+ * serialized into this VM. The return type of the method can be
+ * either {@link Object} or <code>void</code>. If the return type
+ * of the method is <code>void</code>, <code>null</code> is
+ * returned.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public Object invoke(Object o, String methodName) {
+ return invoke(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method can be either {@link
+ * Object} or <code>void</code>. If the return type of the method
+ * is <code>void</code>, <code>null</code> is returned.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public Object invoke(Object o, String methodName, Object[] args) {
+ if (!this.available) {
+ String s = "VM not available: " + this;
+ throw new RMIException(this, o.getClass().getName(), methodName,
+ new IllegalStateException(s));
+ }
+ MethExecutorResult result = null;
+ int retryCount = 120;
+ do {
+ try {
+ if ( args == null )
+ result = this.client.executeMethodOnObject(o, methodName);
+ else
+ result = this.client.executeMethodOnObject(o, methodName, args);
+ break; // out of while loop
+ } catch( RemoteException e ) {
+ if (retryCount-- > 0) {
+ boolean interrupted = Thread.interrupted();
+ try { Thread.sleep(1000); } catch (InterruptedException ignore) {interrupted = true;}
+ finally {
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ } else {
+ throw new RMIException(this, o.getClass().getName(), methodName, e );
+ }
+ }
+ } while (true);
+
+ if (!result.exceptionOccurred()) {
+ return result.getResult();
+
+ } else {
+ Throwable thr = result.getException();
+ throw new RMIException(this, o.getClass().getName(), methodName, thr,
+ result.getStackTrace());
+ }
+ }
+
+ /**
+ * Invokes the <code>main</code> method of a given class
+ *
+ * @param c
+ * The class on which to invoke the <code>main</code> method
+ * @param args
+ * The "command line" arguments to pass to the
+ * <code>main</code> method
+ */
+ public void invokeMain(Class c, String[] args) {
+ Object[] stupid = new Object[] { args };
+ invoke(c, "main", stupid);
+ }
+
+ /**
+ * Asynchronously invokes the <code>main</code> method of a given
+ * class
+ *
+ * @param c
+ * The class on which to invoke the <code>main</code> method
+ * @param args
+ * The "command line" arguments to pass to the
+ * <code>main</code> method
+ */
+ public AsyncInvocation invokeMainAsync(Class c, String[] args) {
+ Object[] stupid = new Object[] { args };
+ return invokeAsync(c, "main", stupid);
+ }
+
+ /**
+ * Invokes a static method with a <code>boolean</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>boolean</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public boolean invokeBoolean(Class c, String methodName) {
+ return invokeBoolean(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>boolean</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>boolean</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public boolean invokeBoolean(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a boolean";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Boolean) {
+ return ((Boolean) result).booleanValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a boolean";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>boolean</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>boolean</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public boolean invokeBoolean(Object o, String methodName) {
+ return invokeBoolean(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>boolean</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>boolean</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public boolean invokeBoolean(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a boolean";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Boolean) {
+ return ((Boolean) result).booleanValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a boolean";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>char</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>char</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public char invokeChar(Class c, String methodName) {
+ return invokeChar(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>char</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>char</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public char invokeChar(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a char";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Character) {
+ return ((Character) result).charValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a char";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>char</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>char</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public char invokeChar(Object o, String methodName) {
+ return invokeChar(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>char</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>char</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public char invokeChar(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a char";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Character) {
+ return ((Character) result).charValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a char";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>byte</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>byte</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public byte invokeByte(Class c, String methodName) {
+ return invokeByte(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>byte</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>byte</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public byte invokeByte(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a byte";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Byte) {
+ return ((Byte) result).byteValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a byte";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>byte</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>byte</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public byte invokeByte(Object o, String methodName) {
+ return invokeByte(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>byte</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>byte</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public byte invokeByte(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a byte";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Byte) {
+ return ((Byte) result).byteValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a byte";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>short</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>short</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public short invokeShort(Class c, String methodName) {
+ return invokeShort(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>short</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>short</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public short invokeShort(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a short";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Short) {
+ return ((Short) result).shortValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a short";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>short</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>short</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public short invokeShort(Object o, String methodName) {
+ return invokeShort(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>short</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>short</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public short invokeShort(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a short";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Short) {
+ return ((Short) result).shortValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a short";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>int</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>int</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public int invokeInt(Class c, String methodName) {
+ return invokeInt(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>int</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>int</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public int invokeInt(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a int";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Integer) {
+ return ((Integer) result).intValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a int";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>int</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>int</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public int invokeInt(Object o, String methodName) {
+ return invokeInt(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>int</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>int</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public int invokeInt(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a int";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Integer) {
+ return ((Integer) result).intValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a int";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>long</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>long</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public long invokeLong(Class c, String methodName) {
+ return invokeLong(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>long</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>long</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public long invokeLong(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a long";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Long) {
+ return ((Long) result).longValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a long";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>long</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>long</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public long invokeLong(Object o, String methodName) {
+ return invokeLong(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>long</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>long</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public long invokeLong(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a long";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Long) {
+ return ((Long) result).longValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a long";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>float</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>float</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public float invokeFloat(Class c, String methodName) {
+ return invokeFloat(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>float</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>float</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public float invokeFloat(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a float";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Float) {
+ return ((Float) result).floatValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a float";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>float</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>float</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public float invokeFloat(Object o, String methodName) {
+ return invokeFloat(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>float</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>float</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public float invokeFloat(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a float";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Float) {
+ return ((Float) result).floatValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a float";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes a static method with a <code>double</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>double</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public double invokeDouble(Class c, String methodName) {
+ return invokeDouble(c, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes a static method with a <code>double</code> return type
+ * in this VM.
+ *
+ * @param c
+ * The class on which to invoke the method
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>double</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public double invokeDouble(Class c, String methodName, Object[] args) {
+ Object result = invoke(c, methodName, args);
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a double";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Double) {
+ return ((Double) result).doubleValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a double";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>double</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>double</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public double invokeDouble(Object o, String methodName) {
+ return invokeDouble(o, methodName, new Object[0]);
+ }
+
+ /**
+ * Invokes an instance method on an object that is serialized into
+ * this VM. The return type of the method is <code>double</code>.
+ *
+ * @param o
+ * The receiver of the method invocation
+ * @param methodName
+ * The name of the method to invoke
+ * @param args
+ * Arguments passed to the method call (must be {@link
+ * java.io.Serializable}).
+ *
+ * @throws IllegalArgumentException
+ * The method does not return a <code>double</code>
+ * @throws RMIException
+ * An exception occurred on while invoking the method in
+ * this VM
+ */
+ public double invokeDouble(Object o, String methodName, Object[] args) {
+ Object result = invoke(o, methodName, args);
+ Class c = o.getClass();
+ if (result == null) {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned null, expected a double";
+ throw new IllegalArgumentException(s);
+
+ } else if (result instanceof Double) {
+ return ((Double) result).doubleValue();
+
+ } else {
+ String s = "Method \"" + methodName + "\" in class \"" +
+ c.getName() + "\" returned a \"" + result.getClass().getName()
+ + "\" expected a double";
+ throw new IllegalArgumentException(s);
+ }
+ }
+
+ /**
+ * Synchronously bounces (mean kills and restarts) this <code>VM</code>.
+ * Concurrent bounce attempts are synchronized but attempts to invoke
+ * methods on a bouncing VM will cause test failure. Tests using bounce
+ * should be placed at the end of the dunit test suite, since an exception
+ * here will cause all tests using the unsuccessfully bounced VM to fail.
+ *
+ * This method is currently not supported by the standalone dunit
+ * runner.
+ *
+ * @throws RMIException if an exception occurs while bouncing this VM, for
+ * example a HydraTimeoutException if the VM fails to stop within {@link
+ * hydra.Prms#maxClientShutdownWaitSec} or restart within {@link
+ * hydra.Prms#maxClientStartupWaitSec}.
+ */
+ public synchronized void bounce() {
+ if (!this.available) {
+ String s = "VM not available: " + this;
+ throw new RMIException(this, this.getClass().getName(), "bounceVM",
+ new IllegalStateException(s));
+ }
+ this.available = false;
+ try {
+ BounceResult result = DUnitEnv.get().bounce(this.pid);
+
+ this.pid = result.getNewPid();
+ this.client = result.getNewClient();
+ this.available = true;
+ } catch (UnsupportedOperationException e) {
+ this.available = true;
+ throw e;
+ } catch (RemoteException e) {
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw, true));
+ RMIException rmie = new RMIException(this, this.getClass().getName(),
+ "bounceVM", e, sw.toString());
+ throw rmie;
+ }
+ }
+
+ ///////////////////// Utility Methods ////////////////////
+
+ public String toString() {
+ return "VM " + this.getPid() + " running on " + this.getHost();
+ }
+
+ public static int getCurrentVMNum() {
+ return DUnitEnv.get().getVMID();
+ }
+
+ public File getWorkingDirectory() {
+ return DUnitEnv.get().getWorkingDirectory(this.getPid());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
new file mode 100755
index 0000000..9653a76
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
@@ -0,0 +1,167 @@
+package com.gemstone.gemfire.test.dunit;
+
+import static com.gemstone.gemfire.test.dunit.Jitter.jitterInterval;
+import static org.junit.Assert.fail;
+
+import com.gemstone.gemfire.internal.cache.LocalRegion;
+
+/**
+ * Extracted from DistributedTestCase
+ */
+public class Wait {
+
+ /**
+ * Wait until given criterion is met
+ *
+ * @param ev criterion to wait on
+ * @param ms total time to wait, in milliseconds
+ * @param interval pause interval between waits
+ * @param throwOnTimeout if false, don't generate an error
+ */
+ public static void waitForCriterion(final WaitCriterion ev, final long ms, final long interval, final boolean throwOnTimeout) {
+ long waitThisTime = jitterInterval(interval);
+ final long tilt = System.currentTimeMillis() + ms;
+ for (;;) {
+ if (ev.done()) {
+ return; // success
+ }
+
+ if (ev instanceof StoppableWaitCriterion) {
+ StoppableWaitCriterion ev2 = (StoppableWaitCriterion)ev;
+ if (ev2.stopWaiting()) {
+ if (throwOnTimeout) {
+ fail("stopWaiting returned true: " + ev.description());
+ }
+ return;
+ }
+ }
+
+ // Calculate time left
+ long timeLeft = tilt - System.currentTimeMillis();
+ if (timeLeft <= 0) {
+ if (!throwOnTimeout) {
+ return; // not an error, but we're done
+ }
+ fail("Event never occurred after " + ms + " ms: " + ev.description());
+ }
+
+ if (waitThisTime > timeLeft) {
+ waitThisTime = timeLeft;
+ }
+
+ // Wait a little bit
+ Thread.yield();
+ try {
+ Thread.sleep(waitThisTime);
+ } catch (InterruptedException e) {
+ fail("interrupted");
+ }
+ }
+ }
+
+ /**
+ * Wait on a mutex. This is done in a loop in order to address the
+ * "spurious wakeup" "feature" in Java.
+ *
+ * @param ev condition to test
+ * @param mutex object to lock and wait on
+ * @param ms total amount of time to wait
+ * @param interval interval to pause for the wait
+ * @param throwOnTimeout if false, no error is thrown.
+ */
+ public static void waitOnMutex(final WaitCriterion ev, final Object mutex, final long ms, final long interval, final boolean throwOnTimeout) {
+ final long tilt = System.currentTimeMillis() + ms;
+ long waitThisTime = jitterInterval(interval);
+ synchronized (mutex) {
+ for (;;) {
+ if (ev.done()) {
+ break;
+ }
+
+ long timeLeft = tilt - System.currentTimeMillis();
+ if (timeLeft <= 0) {
+ if (!throwOnTimeout) {
+ return; // not an error, but we're done
+ }
+ fail("Event never occurred after " + ms + " ms: " + ev.description());
+ }
+
+ if (waitThisTime > timeLeft) {
+ waitThisTime = timeLeft;
+ }
+
+ try {
+ mutex.wait(waitThisTime);
+ } catch (InterruptedException e) {
+ fail("interrupted");
+ }
+ } // for
+ } // synchronized
+ }
+
+ /** pause for a default interval */
+ public static void pause() {
+ pause(250);
+ }
+
+ /**
+ * Use of this function indicates a place in the tests tree where t
+ * he use of Thread.sleep() is
+ * highly questionable.
+ * <p>
+ * Some places in the system, especially those that test expirations and other
+ * timeouts, have a very good reason to call {@link Thread#sleep(long)}. The
+ * <em>other</em> places are marked by the use of this method.
+ *
+ * @param ms
+ */
+ public static final void staticPause(int ms) {
+ final long target = System.currentTimeMillis() + ms;
+ try {
+ for (;;) {
+ long msLeft = target - System.currentTimeMillis();
+ if (msLeft <= 0) {
+ break;
+ }
+ Thread.sleep(msLeft);
+ }
+ }
+ catch (InterruptedException e) {
+ throw new AssertionError("interrupted", e);
+ }
+
+ }
+
+ /**
+ * Blocks until the clock used for expiration on the given region changes.
+ */
+ public static final void waitForExpiryClockToChange(LocalRegion lr) {
+ long startTime = lr.cacheTimeMillis();
+ do {
+ Thread.yield();
+ } while (startTime == lr.cacheTimeMillis());
+ }
+
+ /** pause for specified ms interval
+ * Make sure system clock has advanced by the specified number of millis before
+ * returning.
+ */
+ public static final void pause(int ms) {
+ if (ms > 50) {
+ //getLogWriter().info("Pausing for " + ms + " ms..."/*, new Exception()*/);
+ }
+ final long target = System.currentTimeMillis() + ms;
+ try {
+ for (;;) {
+ long msLeft = target - System.currentTimeMillis();
+ if (msLeft <= 0) {
+ break;
+ }
+ Thread.sleep(msLeft);
+ }
+ }
+ catch (InterruptedException e) {
+ throw new AssertionError("interrupted", e);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/49b2913a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/WaitCriterion.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/WaitCriterion.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/WaitCriterion.java
new file mode 100755
index 0000000..493038e
--- /dev/null
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/WaitCriterion.java
@@ -0,0 +1,11 @@
+package com.gemstone.gemfire.test.dunit;
+
+/**
+ * Extracted from DistributedTestCase
+ */
+public interface WaitCriterion {
+
+ public boolean done();
+
+ public String description();
+}
[6/9] incubator-geode git commit: Reorganization of dunit
Posted by kl...@apache.org.
Reorganization of dunit
Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/fcd21422
Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/fcd21422
Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/fcd21422
Branch: refs/heads/feature/GEODE-217
Commit: fcd214227656a79edc08fecbf655c9ae98114523
Parents: 49b2913
Author: Kirk Lund <kl...@pivotal.io>
Authored: Fri Aug 21 13:14:16 2015 -0700
Committer: Kirk Lund <kl...@pivotal.io>
Committed: Fri Aug 21 13:14:16 2015 -0700
----------------------------------------------------------------------
build.gradle | 5 +-
.../distributed/DistributedMemberDUnitTest.java | 2 +-
.../distributed/HostedLocatorsDUnitTest.java | 4 +-
.../gemfire/internal/cache/BackupDUnitTest.java | 15 +-
.../offheap/OutOfOffHeapMemoryDUnitTest.java | 4 +-
.../internal/process/PidFileJUnitTest.java | 4 +-
.../catchexception/CatchExceptionDUnitTest.java | 63 --
.../catchexception/CatchExceptionJUnitTest.java | 95 ---
.../gemstone/gemfire/test/dunit/DUnitEnv.java | 100 +++
.../gemfire/test/dunit/DistributedTestCase.java | 687 +++++++++----------
.../com/gemstone/gemfire/test/dunit/Invoke.java | 1 -
.../com/gemstone/gemfire/test/dunit/Jitter.java | 2 +-
.../test/dunit/SerializableRunnable.java | 4 +-
.../com/gemstone/gemfire/test/dunit/Wait.java | 3 +
.../gemfire/test/dunit/cache/CacheTestCase.java | 4 +-
.../test/dunit/tests/BasicDUnitTest.java | 9 +-
.../dunit/tests/DUnitFrameworkTestSuite.java | 16 -
.../gemfire/test/dunit/tests/VMDUnitTest.java | 3 +
.../golden/GoldenTestFrameworkTestSuite.java | 27 -
.../test/junit/rules/ExpectedTimeout.java | 164 -----
.../junit/rules/ExpectedTimeoutJUnitTest.java | 188 -----
21 files changed, 462 insertions(+), 938 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 0311206..b98cdf0 100755
--- a/build.gradle
+++ b/build.gradle
@@ -282,13 +282,12 @@ subprojects {
testCompile 'eu.codearte.catch-exception:catch-throwable:1.4.4'
testCompile 'junit:junit:4.12'
testCompile 'org.assertj:assertj-core:2.1.0'
- testCompile 'org.easytesting:fest-test:2.1.0'
- testCompile 'org.mockito:mockito-core:1.10.19'
+ testCompile 'org.easetech:easytest-core:1.3.2'
testCompile 'org.hamcrest:hamcrest-all:1.3'
testCompile 'org.jmock:jmock:2.8.1'
testCompile 'org.jmock:jmock-junit4:2.8.1'
testCompile 'org.jmock:jmock-legacy:2.8.1'
- testCompile 'org.unitils:unitils:3.4.2'
+ testCompile 'org.mockito:mockito-core:1.10.19'
testCompile 'pl.pragmatists:JUnitParams:1.0.4'
testRuntime 'cglib:cglib:3.1'
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/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 e45b02d..1f6edab 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
@@ -281,7 +281,7 @@ public class DistributedMemberDUnitTest extends DistributedTestCase {
public void run() {
InternalDistributedSystem sys = getSystem();
final String expectedMyGroup = makeGroupsString(vm);
- assertEquals(expectedMyGroup, sys.getConfig().getGroups());
+ assertEquals("vm-"+vm, expectedMyGroup, sys.getConfig().getGroups());
DM dm = sys.getDistributionManager();
DistributedMember self = sys.getDistributedMember();
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/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 e74e12f..f77f50d 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
@@ -37,7 +37,7 @@ import com.gemstone.gemfire.test.dunit.SerializableCallable;
import com.gemstone.gemfire.test.dunit.SerializableRunnable;
import com.gemstone.gemfire.test.junit.categories.DistributedTest;
import com.gemstone.gemfire.test.junit.categories.MembershipTest;
-import com.gemstone.gemfire.test.junit.rules.Retry;
+import com.gemstone.gemfire.test.junit.rules.RetryRule;
/**
* Extracted from LocatorLauncherLocalJUnitTest.
@@ -61,7 +61,7 @@ public class HostedLocatorsDUnitTest extends DistributedTestCase {
public final transient Timeout globalTimeout = Timeout.seconds(2 * 60 * 1000);
@Rule
- public final transient Retry retry = new Retry(2);
+ public final transient RetryRule retry = new RetryRule(2);
@Before
public void setUp() throws Exception {
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java
index 5829451..e7b9261 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/cache/BackupDUnitTest.java
@@ -41,9 +41,10 @@ import com.gemstone.gemfire.distributed.internal.DistributionMessageObserver;
import com.gemstone.gemfire.distributed.internal.ReplyMessage;
import com.gemstone.gemfire.internal.FileUtil;
import com.gemstone.gemfire.internal.cache.partitioned.PersistentPartitionedRegionTestBase;
+import com.gemstone.gemfire.internal.process.PidUnavailableException;
+import com.gemstone.gemfire.internal.process.ProcessUtils;
import dunit.AsyncInvocation;
-import dunit.DUnitEnv;
import dunit.Host;
import dunit.SerializableCallable;
import dunit.SerializableRunnable;
@@ -533,10 +534,18 @@ public class BackupDUnitTest extends PersistentPartitionedRegionTestBase {
vm.invoke(validateUserFileBackup);
}
+ private int identifyPid() {
+ try {
+ return ProcessUtils.identifyPid();
+ } catch (PidUnavailableException e) {
+ throw new AssertionError(e.getMessage(), e);
+ }
+ }
+
protected long setBackupFiles(final VM vm) {
SerializableCallable setUserBackups = new SerializableCallable("set user backups") {
public Object call() {
- final int pid = DUnitEnv.get().getPid();
+ final int pid = identifyPid();
File vmdir = new File("userbackup_"+pid);
File test1 = new File(vmdir, "test1");
File test2 = new File(test1, "test2");
@@ -568,7 +577,7 @@ public class BackupDUnitTest extends PersistentPartitionedRegionTestBase {
protected void verifyUserFileRestored(VM vm, final long lm) {
vm.invoke(new SerializableRunnable() {
public void run() {
- final int pid = DUnitEnv.get().getPid();
+ final int pid = identifyPid();
File vmdir = new File("userbackup_"+pid);
File mytext = new File(vmdir, "test1/test2/my.txt");
assertTrue(mytext.exists());
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java
index 644d82c..72b64e6 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/offheap/OutOfOffHeapMemoryDUnitTest.java
@@ -56,7 +56,7 @@ public class OutOfOffHeapMemoryDUnitTest extends CacheTestCase {
}
@Override
- public void tearDown2() throws Exception {
+ public void tearDownBefore() throws Exception {
final SerializableRunnable checkOrphans = new SerializableRunnable() {
@Override
public void run() {
@@ -70,7 +70,7 @@ public class OutOfOffHeapMemoryDUnitTest extends CacheTestCase {
checkOrphans.run();
} finally {
invokeInEveryVM(getClass(), "cleanup");
- super.tearDown2();
+ super.tearDownBefore();
}
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/internal/process/PidFileJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/process/PidFileJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/process/PidFileJUnitTest.java
index e1ad29b..836712b 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/internal/process/PidFileJUnitTest.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/internal/process/PidFileJUnitTest.java
@@ -26,7 +26,7 @@ import org.junit.rules.TemporaryFolder;
import com.gemstone.gemfire.internal.util.StopWatch;
import com.gemstone.gemfire.test.junit.categories.UnitTest;
-import com.gemstone.gemfire.test.junit.rules.ExpectedTimeout;
+import com.gemstone.gemfire.test.junit.rules.ExpectedTimeoutRule;
/**
* Unit tests the PidFile class.
@@ -44,7 +44,7 @@ public class PidFileJUnitTest {
public ExpectedException thrown = ExpectedException.none();
@Rule
- public ExpectedTimeout timeout = ExpectedTimeout.none();
+ public ExpectedTimeoutRule timeout = ExpectedTimeoutRule.none();
protected Mockery mockContext;
private ExecutorService futures;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionDUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionDUnitTest.java
deleted file mode 100755
index a3fc1f1..0000000
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionDUnitTest.java
+++ /dev/null
@@ -1,63 +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 static org.hamcrest.Matchers.instanceOf;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.fail;
-
-import org.junit.Test;
-
-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.SerializableCallable;
-import com.gemstone.gemfire.test.dunit.VM;
-
-/**
- * Using Catch-Exception works well for remote exceptions and asserting details
- * about root cause of RMIExceptions in DUnit tests.
- */
-public class CatchExceptionDUnitTest extends DistributedTestCase {
- private static final long serialVersionUID = 1L;
-
- private static final String REMOTE_THROW_EXCEPTION_MESSAGE = "Throwing remoteThrowException";
-
- @Test
- public void testRemoteInvocationWithException() {
- Host host = Host.getHost(0);
- VM vm = host.getVM(0);
-
- when(vm).invoke(new ThrowBasicTestException());
-
- then(caughtException())
- .isInstanceOf(RMIException.class)
- .hasCause(new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE));
- }
-
- protected static class ThrowBasicTestException extends SerializableCallable<Object> {
- private static final long serialVersionUID = 1L;
-
- @Override
- public Object call() throws Exception {
- throw new BasicTestException(REMOTE_THROW_EXCEPTION_MESSAGE);
- }
- }
-
- 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/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionJUnitTest.java
deleted file mode 100755
index d197745..0000000
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/catchexception/CatchExceptionJUnitTest.java
+++ /dev/null
@@ -1,95 +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;
-
-/**
- * Simple unit tests exercising Catch-Exception with AssertJ, Hamcrest and JUnit.
- */
-public class CatchExceptionJUnitTest {
-
- @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/fcd21422/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 96ebd7d..944ad2e 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
@@ -12,8 +12,16 @@ package com.gemstone.gemfire.test.dunit;
import java.io.File;
import java.rmi.RemoteException;
+import java.util.Iterator;
+import java.util.Map;
import java.util.Properties;
+import com.gemstone.gemfire.LogWriter;
+import com.gemstone.gemfire.distributed.internal.DistributionConfig;
+import com.gemstone.gemfire.distributed.internal.DistributionConfigImpl;
+import com.gemstone.gemfire.internal.logging.LogWriterFactory;
+import com.gemstone.gemfire.internal.logging.ManagerLogWriter;
+
/**
* This class provides an abstraction over the environment
* that is used to run dunit. This will delegate to the hydra
@@ -64,5 +72,97 @@ public abstract class DUnitEnv {
public abstract BounceResult bounce(int pid) throws RemoteException;
public abstract File getWorkingDirectory(int pid);
+
+ //---------------------------------------------------------------------------
+ // static methods
+ //---------------------------------------------------------------------------
+ public static final Properties getAllDistributedSystemProperties(Properties props) { // TODO: delete
+ Properties p = DUnitEnv.get().getDistributedSystemProperties();
+
+ // our tests do not expect auto-reconnect to be on by default
+ if (!p.contains(DistributionConfig.DISABLE_AUTO_RECONNECT_NAME)) {
+ p.put(DistributionConfig.DISABLE_AUTO_RECONNECT_NAME, "true");
+ }
+
+ for (Iterator iter = props.entrySet().iterator();
+ iter.hasNext(); ) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String key = (String) entry.getKey();
+ Object value = entry.getValue();
+ p.put(key, value);
+ }
+ return p;
+ }
+
+ /**
+ * This finds the log level configured for the test run. It should be used
+ * when creating a new distributed system if you want to specify a log level.
+ *
+ * @return the dunit log-level setting
+ */
+ public static String getDUnitLogLevel() { // TODO: delete
+ Properties p = DUnitEnv.get().getDistributedSystemProperties();
+ String result = p.getProperty(DistributionConfig.LOG_LEVEL_NAME);
+ if (result == null) {
+ result = ManagerLogWriter.levelToString(DistributionConfig.DEFAULT_LOG_LEVEL);
+ }
+ return result;
+ }
+
+ /**
+ * Get the port that the standard dunit locator is listening on.
+ * @return
+ */
+ public static int getDUnitLocatorPort() {
+ return DUnitEnv.get().getLocatorPort();
+ }
+
+ /**
+ * Creates a new LogWriter and adds it to the config properties. The config
+ * can then be used to connect to DistributedSystem, thus providing early
+ * access to the LogWriter before connecting. This call does not connect
+ * to the DistributedSystem. It simply creates and returns the LogWriter
+ * that will eventually be used by the DistributedSystem that connects using
+ * config.
+ *
+ * @param config the DistributedSystem config properties to add LogWriter to
+ * @return early access to the DistributedSystem LogWriter
+ */
+ protected static LogWriter createLogWriter(Properties config) {
+ Properties nonDefault = config;
+ if (nonDefault == null) {
+ nonDefault = new Properties();
+ }
+ addHydraProperties(nonDefault);
+
+ DistributionConfig dc = new DistributionConfigImpl(nonDefault);
+ LogWriter logger = LogWriterFactory.createLogWriterLogger(
+ false/*isLoner*/, false/*isSecurityLog*/, dc,
+ false);
+
+ // if config was non-null, then these will be added to it...
+ nonDefault.put(DistributionConfig.LOG_WRITER_NAME, logger);
+
+ return logger;
+ }
+
+ /**
+ * Fetches the GemFireDescription for this test and adds its
+ * DistributedSystem properties to the provided props parameter.
+ *
+ * @param config the properties to add hydra's test properties to
+ */
+ private static void addHydraProperties(Properties config) {
+ Properties p = DUnitEnv.get().getDistributedSystemProperties();
+ for (Iterator iter = p.entrySet().iterator();
+ iter.hasNext(); ) {
+ Map.Entry entry = (Map.Entry) iter.next();
+ String key = (String) entry.getKey();
+ String value = (String) entry.getValue();
+ if (config.getProperty(key) == null) {
+ config.setProperty(key, value);
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedTestCase.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedTestCase.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedTestCase.java
index 5eb3b0b..abb0a95 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedTestCase.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DistributedTestCase.java
@@ -1,11 +1,9 @@
package com.gemstone.gemfire.test.dunit;
+import static com.gemstone.gemfire.test.dunit.DUnitEnv.*;
import static com.gemstone.gemfire.test.dunit.Invoke.*;
-import static com.gemstone.gemfire.test.dunit.Wait.*;
import static org.junit.Assert.*;
-import java.io.File;
-import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
@@ -28,7 +26,6 @@ import com.gemstone.gemfire.distributed.internal.DistributionConfig;
import com.gemstone.gemfire.distributed.internal.DistributionMessageObserver;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem.CreationStackGenerator;
-import com.gemstone.gemfire.distributed.internal.membership.jgroup.MembershipManagerHelper;
import com.gemstone.gemfire.internal.AvailablePort;
import com.gemstone.gemfire.internal.InternalDataSerializer;
import com.gemstone.gemfire.internal.InternalInstantiator;
@@ -42,11 +39,8 @@ 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.ManagerLogWriter;
import com.gemstone.gemfire.internal.logging.log4j.LogWriterLogger;
import com.gemstone.gemfire.management.internal.cli.LogWrapper;
-import com.gemstone.org.jgroups.Event;
-import com.gemstone.org.jgroups.JChannel;
import com.gemstone.org.jgroups.stack.IpAddress;
import com.gemstone.org.jgroups.stack.Protocol;
import com.gemstone.org.jgroups.util.GemFireTracer;
@@ -58,20 +52,22 @@ import com.gemstone.gemfire.test.dunit.standalone.DUnitLauncher;
*
* @author David Whitlock
*/
-@SuppressWarnings({ "deprecation", "serial", "rawtypes" })
+@SuppressWarnings({ "deprecation", "rawtypes" })
public abstract class DistributedTestCase implements java.io.Serializable {
+ private static final long serialVersionUID = 1L;
private static final Logger logger = LogService.getLogger();
private static final LogWriterLogger oldLogger = LogWriterLogger.create(logger);
@Rule
public transient TestName testNameRule = new TestName();
+ private static volatile String previousTestName;
+ private static volatile String testName;
- public static InternalDistributedSystem system;
- private static Class lastSystemCreatedInTest;
- private static Properties lastSystemProperties;
- public static volatile String testName;
+ private static InternalDistributedSystem system;
+ private static Class previousSystemCreatedInTestClass;
+ private static Properties previousProperties;
- public static final boolean logPerTest = Boolean.getBoolean("dunitLogPerTest");
+ private final boolean logPerTest = Boolean.getBoolean("dunitLogPerTest");
/**
* Creates a new <code>DistributedTestCase</code> test.
@@ -80,85 +76,137 @@ public abstract class DistributedTestCase implements java.io.Serializable {
DUnitLauncher.launchIfNeeded();
}
- private static void setUpCreationStackGenerator() {
- // the following is moved from InternalDistributedSystem to fix #51058
- InternalDistributedSystem.TEST_CREATION_STACK_GENERATOR.set(
- new CreationStackGenerator() {
+ //---------------------------------------------------------------------------
+ // setUp methods
+ //---------------------------------------------------------------------------
+
+ @Before
+ public final void setUpDistributedTestCase() throws Exception {
+ setUpCreationStackGenerator();
+ testName = getMethodName();
+
+ 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 + "-" + getClass().getSimpleName() + "." + testName;
+ setUpInVM(vm, testName, vmDefaultDiskStoreName);
+ }
+ }
+ //System.out.println("\n\n[setup] START TEST " + getClass().getSimpleName()+"."+testName+"\n\n");
+ }
+
+ private void setUpInVM(final VM vm, final String testNameToUse, final String diskStoreNameToUse) {
+ vm.invoke(new SerializableRunnable() {
+ private static final long serialVersionUID = 1L;
+
@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");
- }
- return new Throwable("Creating distributed system with the following configuration:\n" + sb.toString());
+ public void run() {
+ setUpCreationStackGenerator();
+ testName = testNameToUse;
+ System.setProperty(HoplogConfig.ALLOW_LOCAL_HDFS_PROP, "true");
+ GemFireCacheImpl.setDefaultDiskStoreName(diskStoreNameToUse); // TODO: not thread safe
}
});
}
- private static void tearDownCreationStackGenerator() {
- InternalDistributedSystem.TEST_CREATION_STACK_GENERATOR.set(InternalDistributedSystem.DEFAULT_CREATION_STACK_GENERATOR);
+ //---------------------------------------------------------------------------
+ // tearDown methods
+ //---------------------------------------------------------------------------
+
+ /**
+ * 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
+ */
+ @After
+ public final void tearDownDistributedTestCase() throws Exception {
+ tearDownBefore();
+ realTearDown();
+ tearDownAfter();
+
+ tearDownCreationStackGenerator();
+ previousTestName = testName;
+ testName = null;
+
+ tearDownInEveryVM();
+ }
+
+ private void tearDownInEveryVM() {
+ invokeInEveryVM(new SerializableRunnable() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void run() {
+ tearDownCreationStackGenerator();
+ previousTestName = testName;
+ testName = null;
+ }
+ });
}
- private Class getTestClass() {
- Class clazz = getClass();
- while (clazz.getDeclaringClass() != null) {
- clazz = clazz.getDeclaringClass();
+ protected void realTearDown() throws Exception {
+ if (logPerTest) {
+ disconnectFromDS();
+ invokeInEveryVM(DistributedTestCase.class, "disconnectFromDS");
}
- return clazz;
+ cleanupAllVms();
}
/**
- * This finds the log level configured for the test run. It should be used
- * when creating a new distributed system if you want to specify a log level.
- *
- * @return the dunit log-level setting
+ * 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()
*/
- public static String getDUnitLogLevel() { // TODO: delete
- Properties p = DUnitEnv.get().getDistributedSystemProperties();
- String result = p.getProperty(DistributionConfig.LOG_LEVEL_NAME);
- if (result == null) {
- result = ManagerLogWriter.levelToString(DistributionConfig.DEFAULT_LOG_LEVEL);
- }
- return result;
+ protected void tearDownBefore() throws Exception {
}
- public final static Properties getAllDistributedSystemProperties(Properties props) { // TODO: delete
- Properties p = DUnitEnv.get().getDistributedSystemProperties();
-
- // our tests do not expect auto-reconnect to be on by default
- if (!p.contains(DistributionConfig.DISABLE_AUTO_RECONNECT_NAME)) {
- p.put(DistributionConfig.DISABLE_AUTO_RECONNECT_NAME, "true");
- }
-
- for (Iterator iter = props.entrySet().iterator();
- iter.hasNext(); ) {
- Map.Entry entry = (Map.Entry) iter.next();
- String key = (String) entry.getKey();
- Object value = entry.getValue();
- p.put(key, value);
- }
- return p;
+ /**
+ * 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 void setSystem(Properties props, DistributedSystem ds) { // TODO: delete
- system = (InternalDistributedSystem)ds;
- lastSystemProperties = props;
- lastSystemCreatedInTest = getTestClass();
+ //---------------------------------------------------------------------------
+ // test name methods
+ //---------------------------------------------------------------------------
+
+ public final String getMethodName() {
+ return this.testNameRule.getMethodName();
}
/**
+ * 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 getClass().getSimpleName() + "_" + getTestName();
+ }
+
+ protected static String getTestName() {
+ return testName;
+ }
+
+ //---------------------------------------------------------------------------
+ // 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
@@ -169,125 +217,127 @@ public abstract class DistributedTestCase implements java.io.Serializable {
* @see hydra.DistributedConnectionMgr#connect
* @since 3.0
*/
- public final InternalDistributedSystem getSystem(Properties props) {
- // Setting the default disk store name is now done in setUp
+ public final InternalDistributedSystem getSystem(Properties properties) {
if (system == null) {
system = InternalDistributedSystem.getAnyInstance();
}
+
if (system == null || !system.isConnected()) {
- // Figure out our distributed system properties
- Properties p = getAllDistributedSystemProperties(props);
- lastSystemCreatedInTest = getTestClass();
+ // there is no previous system yet
+ final Properties newProperties = getAllDistributedSystemProperties(properties);
+ previousSystemCreatedInTestClass = getTestClass();
if (logPerTest) {
- String testMethod = getTestName();
- String testName = lastSystemCreatedInTest.getName() + '-' + testMethod;
- String oldLogFile = p.getProperty(DistributionConfig.LOG_FILE_NAME);
- p.put(DistributionConfig.LOG_FILE_NAME,
- oldLogFile.replace("system.log", testName+".log"));
- String oldStatFile = p.getProperty(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME);
- p.put(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME,
- oldStatFile.replace("statArchive.gfs", testName+".gfs"));
+ newProperties.put(DistributionConfig.LOG_FILE_NAME, getUniqueName() + ".log");
+ newProperties.put(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME, getUniqueName() + ".gfs");
}
- system = (InternalDistributedSystem)DistributedSystem.connect(p);
- lastSystemProperties = p;
+ system = (InternalDistributedSystem)DistributedSystem.connect(newProperties);
+ previousProperties = newProperties;
+
} else {
+ // there is a previous system
boolean needNewSystem = false;
- if(!getTestClass().equals(lastSystemCreatedInTest)) {
- Properties newProps = getAllDistributedSystemProperties(props);
- needNewSystem = !newProps.equals(lastSystemProperties);
- if(needNewSystem) {
- getLogWriter().info(
+ //if (!getUniqueName().equals(previousTestName)) {
+ if (!getTestClass().equals(previousSystemCreatedInTestClass)) {
+ // previous system was created in a previous test class
+ final Properties newProperties = getAllDistributedSystemProperties(properties);
+ if (logPerTest) {
+ newProperties.put(DistributionConfig.LOG_FILE_NAME, getUniqueName() + ".log");
+ newProperties.put(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME, getUniqueName() + ".gfs");
+ }
+ 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 = "
- + lastSystemProperties + "new props=" + newProps);
+ + previousProperties + "new props=" + newProperties);
}
+
} else {
- Properties activeProps = system.getProperties();
- for (Iterator iter = props.entrySet().iterator();
- iter.hasNext(); ) {
- Map.Entry entry = (Map.Entry) iter.next();
- String key = (String) entry.getKey();
- String value = (String) entry.getValue();
- if (!value.equals(activeProps.getProperty(key))) {
+ // 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;
- getLogWriter().info("Forcing DS disconnect. For property " + key
- + " old value = " + activeProps.getProperty(key)
+ logger.info("Forcing DS disconnect. For property " + key
+ + " old value = " + currentProperties.getProperty(key)
+ " new value = " + value);
break;
}
}
}
- if(needNewSystem) {
+
+ if (needNewSystem) {
// the current system does not meet our needs to disconnect and
// call recursively to get a new system.
- getLogWriter().info("Disconnecting from current DS in order to make a new one");
+ logger.info("Disconnecting from current DS in order to make a new one");
disconnectFromDS();
- getSystem(props);
+ getSystem(properties);
}
}
return system;
}
-
- /**
- * Crash the cache in the given VM in such a way that it immediately stops communicating with
- * peers. This forces the VM's membership manager to throw a ForcedDisconnectException by
- * forcibly terminating the JGroups protocol stack with a fake EXIT event.<p>
- *
- * 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 static boolean crashDistributedSystem(VM vm) { // TODO: move
- return (Boolean)vm.invoke(new SerializableCallable("crash distributed system") {
- public Object call() throws Exception {
- DistributedSystem msys = InternalDistributedSystem.getAnyInstance();
- crashDistributedSystem(msys);
- return true;
- }
- });
- }
- /**
- * Crash the cache in the given VM in such a way that it immediately stops communicating with
- * peers. This forces the VM's membership manager to throw a ForcedDisconnectException by
- * forcibly terminating the JGroups protocol stack with a fake EXIT event.<p>
- *
- * 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 static void crashDistributedSystem(final DistributedSystem msys) { // TODO: move
- MembershipManagerHelper.inhibitForcedDisconnectLogging(true);
- MembershipManagerHelper.playDead(msys);
- JChannel c = MembershipManagerHelper.getJChannel(msys);
- Protocol udp = c.getProtocolStack().findProtocol("UDP");
- udp.stop();
- udp.passUp(new Event(Event.EXIT, new RuntimeException("killing member's ds")));
- try {
- MembershipManagerHelper.getJChannel(msys).waitForClose();
- }
- catch (InterruptedException ie) {
- Thread.currentThread().interrupt();
- // attempt rest of work with interrupt bit set
- }
- MembershipManagerHelper.inhibitForcedDisconnectLogging(false);
- WaitCriterion wc = new WaitCriterion() {
- public boolean done() {
- return !msys.isConnected();
- }
- public String description() {
- return "waiting for distributed system to finish disconnecting: " + msys;
- }
- };
-// try {
- waitForCriterion(wc, 10000, 1000, true);
-// } finally {
-// dumpMyThreads(getLogWriter());
+// public /*final*/ InternalDistributedSystem getSystem(Properties props) {
+// // Setting the default disk store name is now done in setUp
+// if (system == null) {
+// system = InternalDistributedSystem.getAnyInstance();
// }
- }
-
- private String getDefaultDiskStoreName() { // TODO: move
- String vmid = System.getProperty("vmid");
- return "DiskStore-" + vmid + "-"+ getTestClass().getCanonicalName() + "." + getTestName();
- }
+// if (system == null || !system.isConnected()) {
+// // Figure out our distributed system properties
+// Properties p = getAllDistributedSystemProperties(props);
+// lastSystemCreatedInTest = getTestClass();
+// if (logPerTest) {
+// String testMethod = getTestName();
+// String testName = lastSystemCreatedInTest.getName() + '-' + testMethod;
+// String oldLogFile = p.getProperty(DistributionConfig.LOG_FILE_NAME);
+// p.put(DistributionConfig.LOG_FILE_NAME,
+// oldLogFile.replace("system.log", testName+".log"));
+// String oldStatFile = p.getProperty(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME);
+// p.put(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME,
+// oldStatFile.replace("statArchive.gfs", testName+".gfs"));
+// }
+// system = (InternalDistributedSystem)DistributedSystem.connect(p);
+// previousProperties = p;
+// } else {
+// boolean needNewSystem = false;
+// if(!getTestClass().equals(lastSystemCreatedInTest)) {
+// Properties newProps = getAllDistributedSystemProperties(props);
+// needNewSystem = !newProps.equals(previousProperties);
+// if(needNewSystem) {
+// getLogWriter().info(
+// "Test class has changed and the new DS properties are not an exact match. "
+// + "Forcing DS disconnect. Old props = "
+// + previousProperties + "new props=" + newProps);
+// }
+// } else {
+// Properties activeProps = system.getProperties();
+// for (Iterator iter = props.entrySet().iterator();
+// iter.hasNext(); ) {
+// Map.Entry entry = (Map.Entry) iter.next();
+// String key = (String) entry.getKey();
+// String value = (String) entry.getValue();
+// if (!value.equals(activeProps.getProperty(key))) {
+// needNewSystem = true;
+// getLogWriter().info("Forcing DS disconnect. For property " + key
+// + " old value = " + activeProps.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.
+// getLogWriter().info("Disconnecting from current DS in order to make a new one");
+// disconnectFromDS();
+// getSystem(props);
+// }
+// }
+// return system;
+// }
/**
* Returns this VM's connection to the distributed system. If
@@ -363,6 +413,10 @@ public abstract class DistributedTestCase implements java.io.Serializable {
return system != null && system.isConnected();
}
+ //---------------------------------------------------------------------------
+ // public methods
+ //---------------------------------------------------------------------------
+
/**
* Returns a <code>Properties</code> object used to configure a
* connection to a {@link
@@ -376,97 +430,92 @@ public abstract class DistributedTestCase implements java.io.Serializable {
return new Properties();
}
- /**
- * Sets up the test (noop).
- */
- @Before
- public final void setUpDistributedTestCase() throws Exception {
- setUpCreationStackGenerator();
- testName = getName();
- System.setProperty(HoplogConfig.ALLOW_LOCAL_HDFS_PROP, "true");
-
- if (testName != null) {
- GemFireCacheImpl.setDefaultDiskStoreName(getDefaultDiskStoreName());
- String baseDefaultDiskStoreName = getTestClass().getCanonicalName() + "." + getTestName();
- 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);
- String vmDefaultDiskStoreName = "DiskStore-" + h + "-" + v + "-" + baseDefaultDiskStoreName;
- vm.invoke(DistributedTestCase.class, "perVMSetUp", new Object[] {testName, vmDefaultDiskStoreName});
- }
- }
- }
- System.out.println("\n\n[setup] START TEST " + getClass().getSimpleName()+"."+testName+"\n\n");
- }
+ //---------------------------------------------------------------------------
+ // delete
+ //---------------------------------------------------------------------------
- public static void perVMSetUp(String name, String defaultDiskStoreName) { // TODO: move
- setTestName(name);
- GemFireCacheImpl.setDefaultDiskStoreName(defaultDiskStoreName);
- System.setProperty(HoplogConfig.ALLOW_LOCAL_HDFS_PROP, "true");
+ public void setSystem(Properties props, DistributedSystem ds) { // TODO: delete
+ system = (InternalDistributedSystem)ds;
+ previousProperties = props;
+ previousSystemCreatedInTestClass = getTestClass();
}
- public static void setTestName(String name) {
- testName = name;
+ //---------------------------------------------------------------------------
+ // private
+ //---------------------------------------------------------------------------
+
+ private Class getTestClass() {
+ Class clazz = getClass();
+ while (clazz.getDeclaringClass() != null) {
+ clazz = clazz.getDeclaringClass();
+ }
+ return clazz;
}
- public static String getTestName() {
- return testName;
- }
-
- /**
- * 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 #tearDown2()} instead.
- * @throws Exception
- */
- @After
- public final void tearDownDistributedTestCase() throws Exception {
- tearDownCreationStackGenerator();
- tearDown2();
- realTearDown();
- tearDownAfter();
+ private String getDefaultDiskStoreName() { // TODO: move
+ String vmid = System.getProperty("vmid");
+ return "DiskStore-" + vmid + "-"+ getTestClass().getCanonicalName() + "." + getTestName();
}
+ //---------------------------------------------------------------------------
+ // deprecated static methods
+ //---------------------------------------------------------------------------
+
/**
- * 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()
+ * Returns a <code>LogWriter</code> for logging information
+ * @deprecated Use a static logger from the log4j2 LogService.getLogger instead.
*/
- // TODO rename this method to tearDownBefore and change the access modifier to protected!
- public void tearDown2() throws Exception { // TODO: rename
+ @Deprecated
+ public static InternalLogWriter getLogWriter() { // TODO: delete
+ return oldLogger;
}
- protected void realTearDown() throws Exception {
- if (logPerTest) {
- disconnectFromDS();
- invokeInEveryVM(DistributedTestCase.class, "disconnectFromDS");
- }
- cleanupAllVms();
+ //---------------------------------------------------------------------------
+ // private static methods
+ //---------------------------------------------------------------------------
+
+ 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");
+ }
+ return new Throwable("Creating distributed system with the following configuration:\n" + sb.toString());
+ }
+ });
}
- /**
- * 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 #tearDown2()
- */
- protected void tearDownAfter() throws Exception {
+ private static void tearDownCreationStackGenerator() {
+ InternalDistributedSystem.TEST_CREATION_STACK_GENERATOR.set(InternalDistributedSystem.DEFAULT_CREATION_STACK_GENERATOR);
}
-
- public static void cleanupAllVms()
- {
+
+ //---------------------------------------------------------------------------
+ // 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();
@@ -475,58 +524,33 @@ public abstract class DistributedTestCase implements java.io.Serializable {
DUnitLauncher.closeAndCheckForSuspects();
}
-
- 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() // TODO: move
- {
+ 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();
}
});
}
- public static void unregisterInstantiatorsInThisVM() { // TODO: move
+ public static void unregisterInstantiatorsInThisVM() {
// unregister all the instantiators
InternalInstantiator.reinitialize();
assertEquals(0, InternalInstantiator.getInstantiators().length);
}
- public static void unregisterDataSerializerInThisVM() // TODO: move
- {
+ public static void unregisterDataSerializerInThisVM() {
DataSerializerPropogationDUnitTest.successfullyLoadedTestDataSerializer = false;
// unregister all the Dataserializers
InternalDataSerializer.reinitialize();
@@ -534,18 +558,15 @@ public abstract class DistributedTestCase implements java.io.Serializable {
assertEquals(0, InternalDataSerializer.getSerializers().length);
}
-
protected static void disconnectAllFromDS() {
disconnectFromDS();
- invokeInEveryVM(DistributedTestCase.class,
- "disconnectFromDS");
+ invokeInEveryVM(DistributedTestCase.class, "disconnectFromDS");
}
/**
* Disconnects this VM from the distributed system
*/
public static void disconnectFromDS() {
- testName = null;
GemFireCacheImpl.testCacheXml = null;
if (system != null) {
system.disconnect();
@@ -565,95 +586,37 @@ public abstract class DistributedTestCase implements java.io.Serializable {
}
}
- {
- AdminDistributedSystemImpl ads =
- AdminDistributedSystemImpl.getConnectedInstance();
- if (ads != null) {// && ads.isConnected()) {
- ads.disconnect();
- }
+ AdminDistributedSystemImpl ads = AdminDistributedSystemImpl.getConnectedInstance();
+ if (ads != null) {// && ads.isConnected()) {
+ ads.disconnect();
}
}
- /**
- * Strip the package off and gives just the class name.
- * Needed because of Windows file name limits.
- */
- private String getShortClassName() {
- String result = this.getClass().getName();
- int idx = result.lastIndexOf('.');
- if (idx != -1) {
- result = result.substring(idx+1);
- }
- return result;
- }
-
- /** get the host name to use for a server cache in client/server dunit
- * testing
- * @param host
- * @return the host name
- */
- public static String getServerHostName(Host host) { // TODO: move
- return System.getProperty("gemfire.server-bind-address") != null?
- System.getProperty("gemfire.server-bind-address")
- : host.getHostName();
- }
-
- /** get the IP literal name for the current host, use this instead of
- * "localhost" to avoid IPv6 name resolution bugs in the JDK/machine config.
- * @return an ip literal, this method honors java.net.preferIPvAddresses
- */
- public static String getIPLiteral() { // TODO: move
- try {
- return SocketCreator.getLocalHost().getHostAddress();
- } catch (UnknownHostException e) {
- throw new Error("problem determining host IP address", e);
+ 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();
}
- }
-
-
- /**
- * Get the port that the standard dunit locator is listening on.
- * @return
- */
- public static int getDUnitLocatorPort() { // TODO: move
- return DUnitEnv.get().getLocatorPort();
- }
-
- public String getName() {
- return this.testNameRule.getMethodName();
- }
-
- /**
- * 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 String getUniqueName() {
- return getClass().getSimpleName() + "_" + getName();
- }
-
- /**
- * 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;
- }
-
- /**
- * Delete locator state files. Use this after getting a random port
- * to ensure that an old locator state file isn't picked up by the
- * new locator you're starting.
- *
- * @param ports
- */
- public static void deleteLocatorStateFile(final int... ports) { // TODO: move
- for (int i=0; i<ports.length; i++) {
- final File stateFile = new File("locator"+ports[i]+"state.dat");
- if (stateFile.exists()) {
- stateFile.delete();
- }
+ ExpectedExceptionString ex;
+ while((ex = ExpectedExceptionString.poll()) != null) {
+ ex.remove();
}
}
-
}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
index bd9eaf6..4ccf972 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Invoke.java
@@ -36,7 +36,6 @@ public class Invoke {
public static void invokeInEveryVM(final SerializableRunnable work) {
for (int h = 0; h < Host.getHostCount(); h++) {
Host host = Host.getHost(h);
-
for (int v = 0; v < host.getVMCount(); v++) {
VM vm = host.getVM(v);
vm.invoke(work);
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
index 446b4bf..698d055 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Jitter.java
@@ -5,7 +5,7 @@ import java.util.Random;
/**
* Extracted from DistributedTestCase
*/
-public class Jitter {
+class Jitter {
/**
* If true, we randomize the amount of time we wait
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
index 28eabc3..df3a429 100644
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/SerializableRunnable.java
@@ -37,9 +37,7 @@ import java.io.Serializable;
* }
* </PRE>
*/
-public abstract class SerializableRunnable
- implements Serializable, Runnable {
-
+public abstract class SerializableRunnable implements Serializable, Runnable {
private static final long serialVersionUID = 7584289978241650456L;
private String name;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
index 9653a76..fa9b591 100755
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
+++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Wait.java
@@ -10,6 +10,9 @@ import com.gemstone.gemfire.internal.cache.LocalRegion;
*/
public class Wait {
+ protected Wait() {
+ }
+
/**
* Wait until given criterion is met
*
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/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
index 8535d85..0dbda35 100755
--- 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
@@ -420,7 +420,7 @@ public abstract class CacheTestCase extends DistributedTestCase {
}
@Override
- public void tearDown2() throws Exception {
+ public void tearDownBefore() throws Exception {
// locally destroy all root regions and close the cache
remoteTearDown();
// Now invoke it in every VM
@@ -431,7 +431,7 @@ public abstract class CacheTestCase extends DistributedTestCase {
vm.invoke(CacheTestCase.class, "remoteTearDown");
}
}
- super.tearDown2();
+ super.tearDownBefore();
}
/**
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/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
index d0b1710..f15fe23 100644
--- 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
@@ -14,17 +14,20 @@ import java.util.Properties;
import org.junit.Ignore;
import org.junit.Test;
+import org.junit.experimental.categories.Category;
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;
+import com.gemstone.gemfire.test.junit.categories.DistributedTest;
/**
* This class tests the basic functionality of the distributed unit
* test framework.
*/
+@Category(DistributedTest.class)
public class BasicDUnitTest extends DistributedTestCase {
private static final long serialVersionUID = 1L;
@@ -58,7 +61,7 @@ public class BasicDUnitTest extends DistributedTestCase {
}
@Test
- public void testRemoteInvokeAsync() throws InterruptedException {
+ public void testRemoteInvokeAsync() throws Exception {
Host host = Host.getHost(0);
VM vm = host.getVM(0);
String name = this.getUniqueName();
@@ -78,7 +81,7 @@ public class BasicDUnitTest extends DistributedTestCase {
}
@Test
- public void testRemoteInvokeAsyncWithException() throws InterruptedException {
+ public void testRemoteInvokeAsyncWithException() throws Exception {
Host host = Host.getHost(0);
VM vm = host.getVM(0);
@@ -93,7 +96,7 @@ public class BasicDUnitTest extends DistributedTestCase {
@Ignore("not implemented")
public void testRemoteInvocationBoolean() {
}
-
+
/**
* Accessed via reflection. DO NOT REMOVE
*/
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/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
deleted file mode 100755
index 82664b2..0000000
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitFrameworkTestSuite.java
+++ /dev/null
@@ -1,16 +0,0 @@
-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/fcd21422/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
index 12faffe..904da4f 100644
--- 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
@@ -15,16 +15,19 @@ import java.io.Serializable;
import java.util.concurrent.atomic.AtomicInteger;
import org.junit.Test;
+import org.junit.experimental.categories.Category;
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;
+import com.gemstone.gemfire.test.junit.categories.DistributedTest;
/**
* This class tests the functionality of the {@link VM} class.
*/
+@Category(DistributedTest.class)
public class VMDUnitTest extends DistributedTestCase {
private static final long serialVersionUID = 1L;
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-core/src/test/java/com/gemstone/gemfire/test/golden/GoldenTestFrameworkTestSuite.java
----------------------------------------------------------------------
diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/golden/GoldenTestFrameworkTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/golden/GoldenTestFrameworkTestSuite.java
deleted file mode 100755
index ed540be..0000000
--- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/golden/GoldenTestFrameworkTestSuite.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.gemstone.gemfire.test.golden;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-@RunWith(Suite.class)
-@Suite.SuiteClasses({
- FailWithErrorInOutputJUnitTest.class,
- FailWithExtraLineInOutputJUnitTest.class,
- FailWithLineMissingFromEndOfOutputJUnitTest.class,
- FailWithLineMissingFromMiddleOfOutputJUnitTest.class,
- FailWithLoggerErrorInOutputJUnitTest.class,
- FailWithLoggerFatalInOutputJUnitTest.class,
- FailWithLoggerWarnInOutputJUnitTest.class,
- FailWithSevereInOutputJUnitTest.class,
- FailWithTimeoutOfWaitForOutputToMatchJUnitTest.class,
- FailWithWarningInOutputJUnitTest.class,
- PassJUnitTest.class,
- PassWithExpectedErrorJUnitTest.class,
- PassWithExpectedSevereJUnitTest.class,
- PassWithExpectedWarningJUnitTest.class,
-})
-/**
- * Suite of tests for the test.golden Golden Test framework classes.
- */
-public class GoldenTestFrameworkTestSuite {
-}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeout.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeout.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeout.java
deleted file mode 100755
index 9d4040a..0000000
--- a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeout.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package com.gemstone.gemfire.test.junit.rules;
-
-import static org.junit.Assert.assertThat;
-
-import java.util.concurrent.TimeUnit;
-
-import org.hamcrest.Matcher;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TestRule;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-
-/**
- * Expect an Exception within a specified timeout.
- *
- * @author Kirk Lund
- * @since 8.2
- */
-public class ExpectedTimeout implements TestRule {
-
- /**
- * @return a Rule that expects no timeout (identical to behavior without this Rule)
- */
- public static ExpectedTimeout none() {
- return new ExpectedTimeout();
- }
-
- private ExpectedException delegate;
- private boolean expectsThrowable;
- private long minDuration;
- private long maxDuration;
- private TimeUnit timeUnit;
-
- private ExpectedTimeout() {
- this.delegate = ExpectedException.none();
- }
-
- public ExpectedTimeout expectMinimumDuration(final long minDuration) {
- this.minDuration = minDuration;
- return this;
- }
- public ExpectedTimeout expectMaximumDuration(final long maxDuration) {
- this.maxDuration = maxDuration;
- return this;
- }
- public ExpectedTimeout expectTimeUnit(final TimeUnit timeUnit) {
- this.timeUnit = timeUnit;
- return this;
- }
-
- public ExpectedTimeout handleAssertionErrors() {
- this.delegate.handleAssertionErrors();
- return this;
- }
-
- public ExpectedTimeout handleAssumptionViolatedExceptions() {
- this.delegate.handleAssumptionViolatedExceptions();
- return this;
- }
-
- /**
- * Adds {@code matcher} to the list of requirements for any thrown
- * exception.
- */
- public void expect(final Matcher<?> matcher) {
- this.delegate.expect(matcher);
- }
-
- /**
- * Adds to the list of requirements for any thrown exception that it should
- * be an instance of {@code type}
- */
- public void expect(final Class<? extends Throwable> type) {
- this.delegate.expect(type);
- this.expectsThrowable = true;
- }
-
- /**
- * Adds to the list of requirements for any thrown exception that it should
- * <em>contain</em> string {@code substring}
- */
- public void expectMessage(final String substring) {
- this.delegate.expectMessage(substring);
- }
-
- /**
- * Adds {@code matcher} to the list of requirements for the message returned
- * from any thrown exception.
- */
- public void expectMessage(final Matcher<String> matcher) {
- this.delegate.expectMessage(matcher);
- }
-
- /**
- * Adds {@code matcher} to the list of requirements for the cause of
- * any thrown exception.
- */
- public void expectCause(final Matcher<? extends Throwable> expectedCause) {
- this.delegate.expectCause(expectedCause);
- }
-
- public boolean expectsTimeout() {
- return minDuration > 0 || maxDuration > 0;
- }
-
- public boolean expectsThrowable() {
- return expectsThrowable = true;
- }
-
- @Override
- public Statement apply(final Statement base, final Description description) {
- Statement next = delegate.apply(base, description);
- return new ExpectedTimeoutStatement(next);
- }
-
- private void handleTime(final Long duration) {
- if (expectsTimeout()) {
- assertThat(timeUnit.convert(duration, TimeUnit.NANOSECONDS), new TimeMatcher(timeUnit, minDuration, maxDuration));
- }
- }
-
- private static class TimeMatcher extends org.hamcrest.TypeSafeMatcher<Long> {
-
- private final TimeUnit timeUnit;
- private final long minDuration;
- private final long maxDuration;
-
- public TimeMatcher(final TimeUnit timeUnit, final long minDuration, final long maxDuration) {
- this.timeUnit = timeUnit;
- this.minDuration = minDuration;
- this.maxDuration = maxDuration;
- }
-
- @Override
- public boolean matchesSafely(final Long duration) {
- return duration >= this.minDuration && duration <= this.maxDuration;
- }
-
- @Override
- public void describeTo(final org.hamcrest.Description description) {
- description.appendText("expects duration to be greater than or equal to ")
- .appendValue(this.minDuration)
- .appendText(" and less than or equal to ")
- .appendValue(this.maxDuration)
- .appendText(" ")
- .appendValue(this.timeUnit);
- }
- }
-
- private class ExpectedTimeoutStatement extends Statement {
- private final Statement next;
-
- public ExpectedTimeoutStatement(final Statement base) {
- next = base;
- }
-
- @Override
- public void evaluate() throws Throwable {
- long start = System.nanoTime();
- next.evaluate();
- handleTime(System.nanoTime() - start);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/fcd21422/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutJUnitTest.java
----------------------------------------------------------------------
diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutJUnitTest.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutJUnitTest.java
deleted file mode 100755
index fe11586..0000000
--- a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/ExpectedTimeoutJUnitTest.java
+++ /dev/null
@@ -1,188 +0,0 @@
-package com.gemstone.gemfire.test.junit.rules;
-
-import static org.hamcrest.core.StringContains.*;
-import static org.hamcrest.core.Is.*;
-import static org.hamcrest.core.IsInstanceOf.*;
-import static org.junit.Assert.*;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-import org.junit.runner.JUnitCore;
-import org.junit.runner.Request;
-import org.junit.runner.Result;
-import org.junit.runner.notification.Failure;
-
-import com.gemstone.gemfire.test.junit.categories.UnitTest;
-
-/**
- * Unit tests for ExpectedTimeout JUnit Rule.
- *
- * @author Kirk Lund
- * @since 8.2
- */
-@Category(UnitTest.class)
-public class ExpectedTimeoutJUnitTest {
-
- @Test
- public void passesUnused() {
- Result result = runTest(PassesUnused.class);
- assertTrue(result.wasSuccessful());
- }
-
- @Test
- public void failsWithoutExpectedException() {
- Result result = runTest(FailsWithoutExpectedException.class);
- assertFalse(result.wasSuccessful());
- List<Failure> failures = result.getFailures();
- assertEquals(1, failures.size());
- Failure failure = failures.get(0);
- assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
- assertThat(failure.getException().getMessage(), containsString("Expected test to throw an instance of " + TimeoutException.class.getName()));
- }
-
- @Test
- public void failsWithoutExpectedTimeoutException() {
- Result result = runTest(FailsWithoutExpectedTimeoutException.class);
- assertFalse(result.wasSuccessful());
- List<Failure> failures = result.getFailures();
- assertEquals(1, failures.size());
- Failure failure = failures.get(0);
- assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
- assertThat(failure.getException().getMessage(), containsString("Expected test to throw (an instance of " + TimeoutException.class.getName() + " and exception with message a string containing \"" + FailsWithoutExpectedTimeoutException.message + "\")"));
- }
-
- @Test
- public void failsWithExpectedTimeoutButWrongError() {
- Result result = runTest(FailsWithExpectedTimeoutButWrongError.class);
- assertFalse(result.wasSuccessful());
- List<Failure> failures = result.getFailures();
- assertEquals(1, failures.size());
- Failure failure = failures.get(0);
- assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
- assertThat(failure.getException().getMessage(), containsString(NullPointerException.class.getName()));
- }
-
- @Test
- public void passesWithExpectedTimeoutAndTimeoutException() {
- Result result = runTest(PassesWithExpectedTimeoutAndTimeoutException.class);
- assertTrue(result.wasSuccessful());
- }
-
- @Test
- public void failsWhenTimeoutIsEarly() {
- Result result = runTest(FailsWhenTimeoutIsEarly.class);
- assertFalse(result.wasSuccessful());
- List<Failure> failures = result.getFailures();
- assertEquals(1, failures.size());
- Failure failure = failures.get(0);
- assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
- assertThat(failure.getException().getMessage(), containsString("Expected test to throw (an instance of " + TimeoutException.class.getName() + " and exception with message a string containing \"" + FailsWhenTimeoutIsEarly.message + "\")"));
- }
-
- @Test
- public void failsWhenTimeoutIsLate() {
- Result result = runTest(FailsWhenTimeoutIsLate.class);
- assertFalse(result.wasSuccessful());
- List<Failure> failures = result.getFailures();
- assertEquals(1, failures.size());
- Failure failure = failures.get(0);
- assertThat(failure.getException(), is(instanceOf(AssertionError.class)));
- assertThat(failure.getException().getMessage(), containsString("Expected test to throw (an instance of " + TimeoutException.class.getName() + " and exception with message a string containing \"" + FailsWhenTimeoutIsLate.message + "\")"));
- }
-
- private static Result runTest(Class<?> test) {
- JUnitCore junitCore = new JUnitCore();
- return junitCore.run(Request.aClass(test).getRunner());
- }
-
- public static class AbstractExpectedTimeoutTest {
- @Rule
- public ExpectedTimeout timeout = ExpectedTimeout.none();
- }
-
- public static class PassesUnused extends AbstractExpectedTimeoutTest {
- @Test
- public void passesUnused() throws Exception {
- }
- }
-
- public static class FailsWithoutExpectedException extends AbstractExpectedTimeoutTest {
- @Test
- public void failsWithoutExpectedException() throws Exception {
- timeout.expect(TimeoutException.class);
- }
- }
-
- public static class FailsWithoutExpectedTimeoutException extends AbstractExpectedTimeoutTest {
- public static final String message = "this is a message for FailsWithoutExpectedTimeoutException";
- @Test
- public void failsWithoutExpectedTimeoutAndTimeoutException() throws Exception {
- timeout.expect(TimeoutException.class);
- timeout.expectMessage(message);
- timeout.expectMinimumDuration(10);
- timeout.expectMaximumDuration(1000);
- timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
- Thread.sleep(100);
- }
- }
-
- public static class FailsWithExpectedTimeoutButWrongError extends AbstractExpectedTimeoutTest {
- public static final String message = "this is a message for FailsWithExpectedTimeoutButWrongError";
- @Test
- public void failsWithExpectedTimeoutButWrongError() throws Exception {
- timeout.expect(TimeoutException.class);
- timeout.expectMessage(message);
- timeout.expectMinimumDuration(10);
- timeout.expectMaximumDuration(1000);
- timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
- Thread.sleep(100);
- throw new NullPointerException();
- }
- }
-
- public static class PassesWithExpectedTimeoutAndTimeoutException extends AbstractExpectedTimeoutTest {
- public static final String message = "this is a message for PassesWithExpectedTimeoutAndTimeoutException";
- public static final Class<TimeoutException> exceptionClass = TimeoutException.class;
- @Test
- public void passesWithExpectedTimeoutAndTimeoutException() throws Exception {
- timeout.expect(exceptionClass);
- timeout.expectMessage(message);
- timeout.expectMinimumDuration(10);
- timeout.expectMaximumDuration(1000);
- timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
- Thread.sleep(100);
- throw new TimeoutException(message);
- }
- }
-
- public static class FailsWhenTimeoutIsEarly extends AbstractExpectedTimeoutTest {
- public static final String message = "this is a message for FailsWhenTimeoutIsEarly";
- @Test
- public void failsWhenTimeoutIsEarly() throws Exception {
- timeout.expect(TimeoutException.class);
- timeout.expectMessage(message);
- timeout.expectMinimumDuration(1000);
- timeout.expectMaximumDuration(2000);
- timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
- Thread.sleep(10);
- }
- }
-
- public static class FailsWhenTimeoutIsLate extends AbstractExpectedTimeoutTest {
- public static final String message = "this is a message for FailsWhenTimeoutIsLate";
- @Test
- public void failsWhenTimeoutIsLate() throws Exception {
- timeout.expect(TimeoutException.class);
- timeout.expectMessage(message);
- timeout.expectMinimumDuration(10);
- timeout.expectMaximumDuration(20);
- timeout.expectTimeUnit(TimeUnit.MILLISECONDS);
- Thread.sleep(100);
- }
- }
-}