Return-Path: X-Original-To: apmail-geode-commits-archive@minotaur.apache.org Delivered-To: apmail-geode-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B23AA10AFF for ; Mon, 14 Sep 2015 17:36:27 +0000 (UTC) Received: (qmail 52786 invoked by uid 500); 14 Sep 2015 17:35:53 -0000 Delivered-To: apmail-geode-commits-archive@geode.apache.org Received: (qmail 52752 invoked by uid 500); 14 Sep 2015 17:35:53 -0000 Mailing-List: contact commits-help@geode.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@geode.incubator.apache.org Delivered-To: mailing list commits@geode.incubator.apache.org Received: (qmail 52743 invoked by uid 99); 14 Sep 2015 17:35:53 -0000 Received: from Unknown (HELO spamd2-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 14 Sep 2015 17:35:53 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd2-us-west.apache.org (ASF Mail Server at spamd2-us-west.apache.org) with ESMTP id BE4CE1A19F0 for ; Mon, 14 Sep 2015 17:35:52 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd2-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.795 X-Spam-Level: * X-Spam-Status: No, score=1.795 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RP_MATCHES_RCVD=-0.006, URIBL_BLOCKED=0.001] autolearn=disabled Received: from mx1-us-west.apache.org ([10.40.0.8]) by localhost (spamd2-us-west.apache.org [10.40.0.9]) (amavisd-new, port 10024) with ESMTP id 1xaIqbqXSZ7Z for ; Mon, 14 Sep 2015 17:35:39 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-us-west.apache.org (ASF Mail Server at mx1-us-west.apache.org) with SMTP id 2F95C206E8 for ; Mon, 14 Sep 2015 17:35:39 +0000 (UTC) Received: (qmail 52034 invoked by uid 99); 14 Sep 2015 17:35:38 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 14 Sep 2015 17:35:38 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 9FFD9E0561; Mon, 14 Sep 2015 17:35:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: klund@apache.org To: commits@geode.incubator.apache.org Date: Mon, 14 Sep 2015 17:35:39 -0000 Message-Id: <25b11f5bafc443739018f8c5a47502a7@git.apache.org> In-Reply-To: <37c27daef70f43468ac4f98d084b7f56@git.apache.org> References: <37c27daef70f43468ac4f98d084b7f56@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/2] incubator-geode git commit: Latest changes for using DUnitTestRule. Latest changes for using DUnitTestRule. Project: http://git-wip-us.apache.org/repos/asf/incubator-geode/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-geode/commit/435dc63c Tree: http://git-wip-us.apache.org/repos/asf/incubator-geode/tree/435dc63c Diff: http://git-wip-us.apache.org/repos/asf/incubator-geode/diff/435dc63c Branch: refs/heads/feature/GEODE-217 Commit: 435dc63c1a12abea17c56f0aca8c455364b63486 Parents: 7c27657 Author: Kirk Lund Authored: Mon Sep 14 10:34:36 2015 -0700 Committer: Kirk Lund Committed: Mon Sep 14 10:34:36 2015 -0700 ---------------------------------------------------------------------- build.gradle | 2 +- .../distributed/DistributedMemberDUnitTest.java | 21 +- .../distributed/HostedLocatorsDUnitTest.java | 25 +- .../LocalDistributionManagerDUnitTest.java | 486 +++++++++++++++++++ .../internal/LocalDistributionManagerTest.java | 475 ------------------ .../gemfire/test/dunit/DUnitTestRule.java | 156 +++++- .../gemstone/gemfire/test/dunit/ThreadDump.java | 157 ------ .../gemstone/gemfire/test/dunit/Threads.java | 161 ++++++ .../dunit/rules/DistributedDisconnectRule.java | 105 ++++ .../rules/DistributedExternalResource.java | 42 ++ .../DistributedRestoreSystemProperties.java | 15 +- .../gemfire/test/dunit/rules/RemoteInvoker.java | 23 + ...ributedRestoreSystemPropertiesDUnitTest.java | 15 +- ...ributedRestoreSystemPropertiesJUnitTest.java | 3 +- .../tests/DUnitTestRuleChainDUnitTest.java | 103 ++++ .../dunit/tests/LogPerTestMethodDUnitTest.java | 12 - .../gemfire/test/dunit/tests/MyTestSuite.java | 3 + .../CatchExceptionExampleDUnitTest.java | 2 +- .../CatchExceptionExampleJUnitTest.java | 2 +- .../rules/SerializableExternalResource.java | 57 ++- .../test/junit/rules/SerializableRuleChain.java | 103 ++++ .../rules/SerializableTemporaryFolder.java | 3 +- .../test/junit/rules/SerializableTestName.java | 3 +- .../test/junit/rules/SerializableTestRule.java | 17 + .../junit/rules/SerializableTestWatcher.java | 4 +- .../test/junit/rules/SerializableTimeout.java | 3 +- .../rules/tests/RuleAndClassRuleJUnitTest.java | 122 +++++ 27 files changed, 1393 insertions(+), 727 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/build.gradle ---------------------------------------------------------------------- diff --git a/build.gradle b/build.gradle index b98cdf0..7b375f8 100755 --- a/build.gradle +++ b/build.gradle @@ -281,7 +281,7 @@ subprojects { 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.assertj:assertj-core:3.1.0' testCompile 'org.easetech:easytest-core:1.3.2' testCompile 'org.hamcrest:hamcrest-all:1.3' testCompile 'org.jmock:jmock:2.8.1' http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/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 8084e54..c54a822 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 @@ -12,9 +12,14 @@ import static com.googlecode.catchexception.CatchException.*; import static com.jayway.awaitility.Awaitility.*; import static com.jayway.awaitility.Duration.*; import static java.util.concurrent.TimeUnit.*; -import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.StrictAssertions.*; import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import com.gemstone.gemfire.IncompatibleSystemException; import com.gemstone.gemfire.distributed.internal.DM; @@ -55,12 +60,12 @@ import com.gemstone.gemfire.test.dunit.VM; * @author Kirk Lund * @since 5.0 */ -@SuppressWarnings("serial") @Category({ DistributedTest.class, MembershipTest.class }) +@SuppressWarnings("serial") public class DistributedMemberDUnitTest implements Serializable { @Rule - public final DUnitTestRule dunitTestRule = new DUnitTestRule(); + public final DUnitTestRule dunitTestRule = DUnitTestRule.build(); private Properties config; @@ -75,10 +80,10 @@ public class DistributedMemberDUnitTest implements Serializable { } @After - public void tearDown() { + public void after() { disconnectAllFromDS(); } - + /** * Tests default configuration values. */ @@ -367,7 +372,7 @@ public class DistributedMemberDUnitTest implements Serializable { final DistributedMember member1 = createSystemAndGetId(vm1, "name1"); final DistributedMember member2 = createSystemAndGetId(vm2, "name2"); - vm0.invoke(new SerializableCallable() { // SerializableRunnable + vm0.invoke(new SerializableCallable() { // SerializableRunnable @Override public Object call() throws Exception { // public void run() DistributedSystem system = getSystem(); @@ -391,7 +396,7 @@ public class DistributedMemberDUnitTest implements Serializable { } private DistributedMember createSystemAndGetId(final VM vm, final String name) { - return (DistributedMember) vm.invoke(new SerializableCallable("create system and get member") { + return (DistributedMember) vm.invoke(new SerializableCallable("create system and get member") { @Override public Object call() throws Exception { final Properties config = createConfig(); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/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 779888b..4588651 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,8 +1,10 @@ package com.gemstone.gemfire.distributed; import static com.gemstone.gemfire.test.dunit.DUnitTestRule.*; +import static com.gemstone.gemfire.test.dunit.Invoke.*; import static com.jayway.awaitility.Awaitility.*; import static java.util.concurrent.TimeUnit.*; +import static org.assertj.core.api.Assertions.*; import static org.junit.Assert.*; import java.io.File; @@ -37,6 +39,7 @@ import com.gemstone.gemfire.test.dunit.SerializableRunnable; import com.gemstone.gemfire.test.dunit.rules.DistributedRestoreSystemProperties; import com.gemstone.gemfire.test.junit.categories.DistributedTest; import com.gemstone.gemfire.test.junit.categories.MembershipTest; +import com.gemstone.gemfire.test.junit.rules.SerializableExternalResource; /** * Extracted from LocatorLauncherLocalJUnitTest. @@ -53,29 +56,13 @@ public class HostedLocatorsDUnitTest implements Serializable { protected transient volatile int locatorPort; protected transient volatile LocatorLauncher launcher; -// @Rule -// public transient RuleChain chain = RuleChain -// .outerRule(new DUnitTestRule()) -// .around(new DistributedRestoreSystemProperties()); - - @Rule public final DUnitTestRule dunitTestRule = DUnitTestRule.builder() .disconnectBefore(true) .disconnectAfter(true) - .chainRule(new DistributedRestoreSystemProperties()) + .innerRule(new DistributedRestoreSystemProperties()) .build(); -// @Before -// public void before() { -// disconnectAllFromDS(); -// } -// -// @After -// public void after() { -// disconnectAllFromDS(); -// } - @Test public void getAllHostedLocators() throws Exception { final InternalDistributedSystem system = getSystem(); @@ -111,8 +98,8 @@ public class HostedLocatorsDUnitTest implements Serializable { with().pollInterval(10, MILLISECONDS).await().atMost(TIMEOUT_MINUTES, MINUTES).until( isLocatorStarted() ); return null; } finally { - System.clearProperty("gemfire.locators"); - System.clearProperty("gemfire.mcast-port"); +// System.clearProperty("gemfire.locators"); +// System.clearProperty("gemfire.mcast-port"); } } }); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/internal/LocalDistributionManagerDUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/internal/LocalDistributionManagerDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/internal/LocalDistributionManagerDUnitTest.java new file mode 100644 index 0000000..0fe28bd --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/internal/LocalDistributionManagerDUnitTest.java @@ -0,0 +1,486 @@ +/*========================================================================= + * 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.distributed.internal; + +import static com.gemstone.gemfire.test.dunit.DUnitTestRule.*; +import static com.gemstone.gemfire.test.dunit.Threads.*; +import static com.gemstone.gemfire.test.dunit.Wait.*; +import static org.assertj.core.api.StrictAssertions.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +import org.junit.Before; +import org.junit.Ignore; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.categories.MembershipTest; +import com.gemstone.gemfire.distributed.internal.membership.InternalDistributedMember; +import com.gemstone.gemfire.test.dunit.AsyncInvocation; +import com.gemstone.gemfire.test.dunit.DUnitTestRule; +import com.gemstone.gemfire.test.dunit.Host; +import com.gemstone.gemfire.test.dunit.SerializableRunnable; +import com.gemstone.gemfire.test.dunit.VM; +import com.gemstone.gemfire.test.dunit.WaitCriterion; + +/** + * This class tests the functionality of a {@link + * LocalDistributionManager}. + * + * @author David Whitlock + * + * @since 2.1 + */ +@Category({ DistributedTest.class, MembershipTest.class }) +@SuppressWarnings("serial") +public class LocalDistributionManagerDUnitTest implements Serializable { + + @Rule + public final DUnitTestRule dunitTestRule = DUnitTestRule.build(); + + @Before + public void before() { + disconnectAllFromDS(); + } + + /** A TestMembershipListener used in this VM */ + protected static TestMembershipListener listener = null; + + /** + * Creates a connection to the distributed system in the given + * {@link VM}. Configures the connection for the VM. + */ + protected void createSystem(VM vm) { + vm.invoke(new SerializableRunnable("Connect to distributed system") { + public void run() { + getSystem(); + } + }); + } + + /** + * Do we see all of the distribution managers in the distributed + * system? + */ + @Test + public void testCountDMs() { + Host host = Host.getHost(0); + VM vm0 = host.getVM(0); + VM vm1 = host.getVM(1); + + createSystem(vm0); + vm0.invoke(new SerializableRunnable("Count DMs") { + public void run() { + DM dm = getSystem().getDistributionManager(); + assertEquals(1, + dm.getNormalDistributionManagerIds().size()); + } + }); + + createSystem(vm1); + vm1.invoke(new SerializableRunnable("Count DMs Again") { + public void run() { + DM dm = getSystem().getDistributionManager(); + assertEquals(2, + dm.getNormalDistributionManagerIds().size()); + } + }); + } + + /** + * Test that messages that are sent are received in a reasonable + * amount of time. + */ + @Test + public void testSendMessage() throws Exception { + Host host = Host.getHost(0); + VM vm0 = host.getVM(0); + VM vm1 = host.getVM(1); + + createSystem(vm0); + createSystem(vm1); + + vm0.invoke(new SerializableRunnable("Send message") { + public void run() { + DM dm = getSystem().getDistributionManager(); + assertEquals("For DM " + dm.getId(), + 1, dm.getOtherNormalDistributionManagerIds().size()); + FirstMessage message = new FirstMessage(); + dm.putOutgoing(message); + } + }); + + vm1.invoke(new SerializableRunnable("Was message received?") { + public void run() { + WaitCriterion ev = new WaitCriterion() { + public boolean done() { + return FirstMessage.received; + } + public String description() { + return null; + } + }; + waitForCriterion(ev, 3 * 1000, 200, true); + FirstMessage.received = false; + } + }); + } + + /** + * Tests the new non-shared {@link ReplyProcessor21} + */ + @Ignore("Fails with too many responses. TODO: confirm if this is still a valid test.") + @Test + public void testReplyProcessor() throws Exception { + Host host = Host.getHost(0); + VM vm0 = host.getVM(0); + VM vm1 = host.getVM(1); + + createSystem(vm0); + createSystem(vm1); + + vm0.invoke(new SerializableRunnable("Send request") { + public void run() { + // Send a request, wait for a response + DM dm = getSystem().getDistributionManager(); + int expected = dm.getOtherNormalDistributionManagerIds().size(); + assertEquals("For DM " + dm.getId(), 1, expected); + + Response.totalResponses = 0; + + Request request = new Request(); + ReplyProcessor21 processor = new ReplyProcessor21(getSystem(), + dm.getOtherNormalDistributionManagerIds()); + request.processorId = processor.getProcessorId(); + dm.putOutgoing(request); + try { + processor.waitForReplies(); + + } catch (Exception ex) { + fail("While waiting for replies", ex); + } + + assertEquals(expected, Response.totalResponses); + } + }); + + } + + /** + * Does the {@link MembershipListener#memberJoined} method get + * invoked? + */ + @Test + public void testMemberJoinedAndDeparted() throws Exception { + + Host host = Host.getHost(0); + VM vm0 = host.getVM(0); + VM vm1 = host.getVM(1); + + createSystem(vm0); + vm0.invoke(new SerializableRunnable("Install listener") { + public void run() { + DM dm = getSystem().getDistributionManager(); + listener = new TestMembershipListener(); + dm.addMembershipListener(listener); + } + }); + createSystem(vm1); + + vm0.invoke(new SerializableRunnable("Verify member joining") { + public void run() { + WaitCriterion ev = new WaitCriterion() { + public boolean done() { + return listener.memberJoined(); + } + public String description() { + return null; + } + }; + waitForCriterion(ev, 3 * 1000, 200, true); + } + }); + vm1.invoke(new SerializableRunnable("Disconnect from system") { + public void run() { + getSystem().disconnect(); + } + }); + + vm0.invoke(new SerializableRunnable("Verify member departing") { + public void run() { + WaitCriterion ev = new WaitCriterion() { + public boolean done() { + return listener.memberDeparted(); + } + public String description() { + return null; + } + }; + waitForCriterion(ev, 3 * 1000, 200, true); + } + }); + } + + /** + * Tests that the reply processor gets signaled when members go + * away. + */ + @Test + public void testMembersDepartWhileWaiting() throws Exception { + + Host host = Host.getHost(0); + VM vm0 = host.getVM(0); + VM vm1 = host.getVM(1); + + createSystem(vm0); + createSystem(vm1); + + AsyncInvocation ai0 = + vm0.invokeAsync(new SerializableRunnable("Send message and wait") { + public void run() { + DM dm = getSystem().getDistributionManager(); + OnlyGFDMReply message = new OnlyGFDMReply(); + ReplyProcessor21 processor = new ReplyProcessor21(getSystem(), + dm.getOtherNormalDistributionManagerIds()); + message.processorId = processor.getProcessorId(); + dm.putOutgoing(message); + + try { + processor.waitForReplies(); + + } catch (Exception ex) { + fail("While waiting for replies", ex); + } + } + }); + + vm1.invoke(new SerializableRunnable("Disconnect from system") { + public void run() { + getSystem().disconnect(); + } + }); + + join(ai0, 30 * 1000); + if (ai0.exceptionOccurred()) { + fail("got exception", ai0.getException()); + } + } + + /** + * A message that is send, and when received, sets a + * boolean static field. + * + * @see LocalDistributionManagerDUnitTest#testSendMessage + */ + public static class FirstMessage extends SerialDistributionMessage { + + /** Has a FirstMessage be received? */ + public static boolean received = false; + + public FirstMessage() { } // For Externalizable + + public void process(DistributionManager dm) { + received = true; + } + public int getDSFID() { + return NO_FIXED_ID; + } + } + + /** + * A request that is replied to with a {@link Response} + * + * @see LocalDistributionManagerDUnitTest#testReplyProcessor + */ + public static class Request extends SerialDistributionMessage + implements MessageWithReply { + + /** The id of the processor to process the response */ + int processorId; + + public Request() { } // For Externizable + + public int getProcessorId() { + return this.processorId; + } + + /** + * Reply with a {@link Response} + */ + public void process(DistributionManager dm) { + Response response = new Response(); + response.processorId = this.processorId; + response.setRecipient(this.getSender()); + dm.putOutgoing(response); + } + + public int getDSFID() { + return NO_FIXED_ID; + } + + public void toData(DataOutput out) throws IOException { + super.toData(out); + out.writeInt(this.processorId); + } + + public void fromData(DataInput in) + throws ClassNotFoundException, IOException { + super.fromData(in); + this.processorId = in.readInt(); + } + + public String toString() { + return "Request with processor " + this.processorId; + } + } + + /** + * A response to a {@link Request} + * + * @see LocalDistributionManagerDUnitTest#testReplyProcessor + */ + public static class Response extends SerialDistributionMessage { + /** The total number of responses that have been received */ + static int totalResponses = 0; + + /** The id of the processor to process the response */ + int processorId; + + public Response() { } // For Externalizable + + /** + * Alert the {@link ReplyProcess21} that this reply has been + * received. + */ + public void process(DistributionManager dm) { + // Look up the processor + ReplyProcessor21 processor = + ReplyProcessor21.getProcessor(this.processorId); + assertNotNull("Null processor!", processor); + synchronized (Response.class) { + totalResponses++; + } + processor.process(this); + } + + public int getDSFID() { + return NO_FIXED_ID; + } + + public void toData(DataOutput out) throws IOException { + super.toData(out); + out.writeInt(this.processorId); + } + + public void fromData(DataInput in) + throws ClassNotFoundException, IOException { + super.fromData(in); + this.processorId = in.readInt(); + } + + public String toString() { + return "Response with processor " + this.processorId; + } + } + + /** + * A MembershipListener that remembers when members + * join and depart. + */ + static class TestMembershipListener implements MembershipListener { + + /** Has a member joined recently? */ + private boolean joined = false; + + /** Has a member departed recently? */ + private boolean departed = false; + + public void memberJoined(InternalDistributedMember id) { + this.joined = true; + } + + public void memberDeparted(InternalDistributedMember id, boolean crashed) { + this.departed = true; + } + + /** + * Gets (and then forgets) whether or not a member has recently + * joined the distributed system. + */ + public boolean memberJoined() { + boolean b = this.joined; + this.joined = false; + return b; + } + + public void quorumLost(Set failures, List remaining) { + } + + public void memberSuspect(InternalDistributedMember id, + InternalDistributedMember whoSuspected) { + } + + /** + * Gets (and then forgets) whether or not a member has recently + * departed the distributed system. + */ + public boolean memberDeparted() { + boolean b = this.departed; + this.departed = false; + return b; + } + } + + /** + * A message that only GemFire distribution managers reply to. + */ + public static class OnlyGFDMReply extends SerialDistributionMessage + implements MessageWithReply { + + /** The id of the processor that processes the reply */ + protected int processorId; + + public int getProcessorId() { + return this.processorId; + } + + public OnlyGFDMReply() { } // For Externalizable + + public void process(DistributionManager dm) { + } + + public int getDSFID() { + return NO_FIXED_ID; + } + + public void toData(DataOutput out) throws IOException { + super.toData(out); + out.writeInt(this.processorId); + } + + public void fromData(DataInput in) + throws ClassNotFoundException, IOException { + super.fromData(in); + this.processorId = in.readInt(); + } + + public String toString() { + return "Only GFDM replies with processor " + this.processorId; + } + } + +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/internal/LocalDistributionManagerTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/internal/LocalDistributionManagerTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/internal/LocalDistributionManagerTest.java deleted file mode 100644 index 55475b3..0000000 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/distributed/internal/LocalDistributionManagerTest.java +++ /dev/null @@ -1,475 +0,0 @@ -/*========================================================================= - * 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.distributed.internal; - -//import com.gemstone.gemfire.*; -//import com.gemstone.gemfire.distributed.DistributedSystem; -import dunit.*; - -import java.util.*; -import java.io.*; -import com.gemstone.gemfire.distributed.internal.membership.*; - -/** - * This class tests the functionality of a {@link - * LocalDistributionManager}. - * - * @author David Whitlock - * - * @since 2.1 - */ -public class LocalDistributionManagerTest - extends DistributedTestCase { - - public LocalDistributionManagerTest(String name) { - super(name); - } - - /** - * Creates a connection to the distributed system in the given - * {@link VM}. Configures the connection for the VM. - */ - protected void createSystem(VM vm) { - vm.invoke(new SerializableRunnable("Connect to distributed system") { - public void run() { - // @todo davidw Remove reliance on shared memory for - // configuration - Properties props = new Properties(); - // props.setProperty(DistributionConfig.ENABLE_SHARED_MEMORY_NAME, "true"); -// File sysDir = -// GemFireConnectionFactory.getInstance().getSystemDirectory(); -// props.setProperty(DistributionConfig.SYSTEM_DIRECTORY_NAME, sysDir.getPath()); - getSystem(props); - } - }); - } - - //////// Test Methods - - /** - * Do we see all of the distribution managers in the distributed - * system? - */ - public void testCountDMs() { - Host host = Host.getHost(0); - VM vm0 = host.getVM(0); - VM vm1 = host.getVM(1); - final int systemCount = 2; - - createSystem(vm0); - vm0.invoke(new SerializableRunnable("Count DMs") { - public void run() { - DM dm = getSystem().getDistributionManager(); - assertEquals(systemCount + 1, - dm.getNormalDistributionManagerIds().size()); - } - }); - createSystem(vm1); - vm1.invoke(new SerializableRunnable("Count DMs Again") { - public void run() { - DM dm = getSystem().getDistributionManager(); - assertEquals(systemCount + 2, - dm.getNormalDistributionManagerIds().size()); - } - }); - } - - /** - * Test that messages that are sent are received in a reasonable - * amount of time. - */ - public void testSendMessage() throws InterruptedException { - Host host = Host.getHost(0); - VM vm0 = host.getVM(0); - VM vm1 = host.getVM(1); - - createSystem(vm0); - createSystem(vm1); - - Thread.sleep(5 * 1000); - - vm0.invoke(new SerializableRunnable("Send message") { - public void run() { - DM dm = getSystem().getDistributionManager(); - assertEquals("For DM " + dm.getId(), - 3, dm.getOtherNormalDistributionManagerIds().size()); - FirstMessage message = new FirstMessage(); - dm.putOutgoing(message); - } - }); - - Thread.sleep(3 * 1000); - - vm1.invoke(new SerializableRunnable("Was message received?") { - public void run() { - WaitCriterion ev = new WaitCriterion() { - public boolean done() { - return FirstMessage.received; - } - public String description() { - return null; - } - }; - DistributedTestCase.waitForCriterion(ev, 3 * 1000, 200, true); - FirstMessage.received = false; - } - }); - } - - /** - * Tests the new non-shared {@link ReplyProcessor21} - */ - public void testReplyProcessor() throws InterruptedException { - Host host = Host.getHost(0); - VM vm0 = host.getVM(0); - VM vm1 = host.getVM(1); - - createSystem(vm0); - createSystem(vm1); - - Thread.sleep(2 * 1000); - - vm0.invoke(new SerializableRunnable("Send request") { - public void run() { - // Send a request, wait for a response - DM dm = getSystem().getDistributionManager(); - int expected = dm.getOtherNormalDistributionManagerIds().size(); - assertEquals("For DM " + dm.getId(), 3, expected); - - Response.totalResponses = 0; - - Request request = new Request(); - ReplyProcessor21 processor = new ReplyProcessor21(getSystem(), - dm.getOtherNormalDistributionManagerIds()); - request.processorId = processor.getProcessorId(); - dm.putOutgoing(request); - try { - processor.waitForReplies(); - - } catch (Exception ex) { - fail("While waiting for replies", ex); - } - - assertEquals(expected, Response.totalResponses); - } - }); - - } - - /** A TestMembershipListener used in this VM */ - protected static TestMembershipListener listener = null; - - /** - * Does the {@link MembershipListener#memberJoined} method get - * invoked? - */ - public void testMemberJoinedAndDeparted() - throws InterruptedException { - - Host host = Host.getHost(0); - VM vm0 = host.getVM(0); - VM vm1 = host.getVM(1); - - createSystem(vm0); - vm0.invoke(new SerializableRunnable("Install listener") { - public void run() { - DM dm = getSystem().getDistributionManager(); - listener = new TestMembershipListener(); - dm.addMembershipListener(listener); - } - }); - createSystem(vm1); - - vm0.invoke(new SerializableRunnable("Verify member joining") { - public void run() { - WaitCriterion ev = new WaitCriterion() { - public boolean done() { - return listener.memberJoined(); - } - public String description() { - return null; - } - }; - DistributedTestCase.waitForCriterion(ev, 3 * 1000, 200, true); - } - }); - vm1.invoke(new SerializableRunnable("Disconnect from system") { - public void run() { - getSystem().disconnect(); - } - }); - - vm0.invoke(new SerializableRunnable("Verify member departing") { - public void run() { - WaitCriterion ev = new WaitCriterion() { - public boolean done() { - return listener.memberDeparted(); - } - public String description() { - return null; - } - }; - DistributedTestCase.waitForCriterion(ev, 3 * 1000, 200, true); - } - }); - } - - /** - * Tests that the reply processor gets signaled when members go - * away. - */ - public void testMembersDepartWhileWaiting() - throws InterruptedException { - - Host host = Host.getHost(0); - VM vm0 = host.getVM(0); - VM vm1 = host.getVM(1); - - createSystem(vm0); - createSystem(vm1); - - Thread.sleep(3 * 1000); - - AsyncInvocation ai0 = - vm0.invokeAsync(new SerializableRunnable("Send message and wait") { - public void run() { - DM dm = getSystem().getDistributionManager(); - OnlyGFDMReply message = new OnlyGFDMReply(); - ReplyProcessor21 processor = new ReplyProcessor21(getSystem(), - dm.getOtherNormalDistributionManagerIds()); - message.processorId = processor.getProcessorId(); - dm.putOutgoing(message); - - try { - processor.waitForReplies(); - - } catch (Exception ex) { - fail("While waiting for replies", ex); - } - } - }); - - Thread.sleep(3 * 1000); - vm1.invoke(new SerializableRunnable("Disconnect from system") { - public void run() { - getSystem().disconnect(); - } - }); - - DistributedTestCase.join(ai0, 30 * 1000, getLogWriter()); - if (ai0.exceptionOccurred()) { - fail("got exception", ai0.getException()); - } - } - - ////////////////////// Inner Classes ////////////////////// - - /** - * A message that is send, and when received, sets a - * boolean static field. - * - * @see LocalDistributionManagerTest#testSendMessage - */ - public static class FirstMessage extends SerialDistributionMessage { - - /** Has a FirstMessage be received? */ - public static boolean received = false; - - public FirstMessage() { } // For Externalizable - - public void process(DistributionManager dm) { - received = true; - } - public int getDSFID() { - return NO_FIXED_ID; - } - } - - /** - * A request that is replied to with a {@link Response} - * - * @see LocalDistributionManagerTest#testReplyProcessor - */ - public static class Request extends SerialDistributionMessage - implements MessageWithReply { - - /** The id of the processor to process the response */ - int processorId; - - public Request() { } // For Externizable - - public int getProcessorId() { - return this.processorId; - } - - /** - * Reply with a {@link Response} - */ - public void process(DistributionManager dm) { - Response response = new Response(); - response.processorId = this.processorId; - response.setRecipient(this.getSender()); - dm.putOutgoing(response); - } - - public int getDSFID() { - return NO_FIXED_ID; - } - - public void toData(DataOutput out) throws IOException { - super.toData(out); - out.writeInt(this.processorId); - } - - public void fromData(DataInput in) - throws ClassNotFoundException, IOException { - super.fromData(in); - this.processorId = in.readInt(); - } - - public String toString() { - return "Request with processor " + this.processorId; - } - } - - /** - * A response to a {@link Request} - * - * @see LocalDistributionManagerTest#testReplyProcessor - */ - public static class Response extends SerialDistributionMessage { - /** The total number of responses that have been received */ - static int totalResponses = 0; - - /** The id of the processor to process the response */ - int processorId; - - public Response() { } // For Externalizable - - /** - * Alert the {@link ReplyProcess21} that this reply has been - * received. - */ - public void process(DistributionManager dm) { - // Look up the processor - ReplyProcessor21 processor = - ReplyProcessor21.getProcessor(this.processorId); - assertNotNull("Null processor!", processor); - synchronized (Response.class) { - totalResponses++; - } - processor.process(this); - } - - public int getDSFID() { - return NO_FIXED_ID; - } - - public void toData(DataOutput out) throws IOException { - super.toData(out); - out.writeInt(this.processorId); - } - - public void fromData(DataInput in) - throws ClassNotFoundException, IOException { - super.fromData(in); - this.processorId = in.readInt(); - } - - public String toString() { - return "Response with processor " + this.processorId; - } - } - - /** - * A MembershipListener that remembers when members - * join and depart. - */ - static class TestMembershipListener implements MembershipListener { - - /** Has a member joined recently? */ - private boolean joined = false; - - /** Has a member departed recently? */ - private boolean departed = false; - - public void memberJoined(InternalDistributedMember id) { - this.joined = true; - } - - public void memberDeparted(InternalDistributedMember id, boolean crashed) { - this.departed = true; - } - - /** - * Gets (and then forgets) whether or not a member has recently - * joined the distributed system. - */ - public boolean memberJoined() { - boolean b = this.joined; - this.joined = false; - return b; - } - - public void quorumLost(Set failures, List remaining) { - } - - public void memberSuspect(InternalDistributedMember id, - InternalDistributedMember whoSuspected) { - } - - /** - * Gets (and then forgets) whether or not a member has recently - * departed the distributed system. - */ - public boolean memberDeparted() { - boolean b = this.departed; - this.departed = false; - return b; - } - } - - /** - * A message that only GemFire distribution managers reply to. - */ - public static class OnlyGFDMReply extends SerialDistributionMessage - implements MessageWithReply { - - /** The id of the processor that processes the reply */ - protected int processorId; - - public int getProcessorId() { - return this.processorId; - } - - public OnlyGFDMReply() { } // For Externalizable - - public void process(DistributionManager dm) { - } - - public int getDSFID() { - return NO_FIXED_ID; - } - - public void toData(DataOutput out) throws IOException { - super.toData(out); - out.writeInt(this.processorId); - } - - public void fromData(DataInput in) - throws ClassNotFoundException, IOException { - super.fromData(in); - this.processorId = in.readInt(); - } - - public String toString() { - return "Only GFDM replies with processor " + this.processorId; - } - } - -} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java index ac2e4c0..e994167 100755 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/DUnitTestRule.java @@ -13,6 +13,7 @@ import java.util.Map; import java.util.Properties; import org.apache.logging.log4j.Logger; +import org.junit.rules.RuleChain; import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; @@ -43,12 +44,19 @@ import com.gemstone.gemfire.internal.cache.tier.sockets.DataSerializerPropogatio import com.gemstone.gemfire.internal.logging.LogService; import com.gemstone.gemfire.management.internal.cli.LogWrapper; import com.gemstone.gemfire.test.dunit.standalone.DUnitLauncher; +import com.gemstone.gemfire.test.junit.rules.SerializableTestRule; import com.gemstone.org.jgroups.stack.IpAddress; import com.gemstone.org.jgroups.stack.Protocol; import com.gemstone.org.jgroups.util.GemFireTracer; +/** + * TestRule for DistributedTest. Use this for DUnit tests using JUnit 4.x + * syntax instead of extending DistributedTestCase. + * + * @author Kirk Lund + */ @SuppressWarnings("serial") -public class DUnitTestRule implements TestRule, Serializable { +public class DUnitTestRule implements SerializableTestRule { private static final Logger logger = LogService.getLogger(); private static final String LOG_PER_TEST_CLASS_PROPERTY = "dunitLogPerTest"; @@ -56,9 +64,13 @@ public class DUnitTestRule implements TestRule, Serializable { private volatile String className; private volatile String methodName; + private final boolean disconnectBeforeClass; + private final boolean disconnectAfterClass; private final boolean disconnectBefore; private final boolean disconnectAfter; + private final transient RuleChain ruleChain; + private static class StaticContext { private static volatile boolean logPerTestClass; private static volatile boolean logPerTestMethod; @@ -75,26 +87,100 @@ public class DUnitTestRule implements TestRule, Serializable { return new Builder(); } + public static DUnitTestRule build() { + return new Builder().build(); + } + protected DUnitTestRule(final Builder builder) { StaticContext.logPerTestClass = builder.logPerTestClass; StaticContext.logPerTestMethod = builder.logPerTestMethod; + this.disconnectBeforeClass = builder.disconnectBeforeClass; + this.disconnectAfterClass = builder.disconnectAfterClass; this.disconnectBefore = builder.disconnectBefore; this.disconnectAfter = builder.disconnectAfter; - if (!builder.ruleChain.isEmpty()) { - + this.ruleChain = buildRuleChain(builder, new ThisRule()); + } + + private static RuleChain buildRuleChain(final Builder builder, final ThisRule thisRule) { + final List rules = new ArrayList(); + + for (TestRule testRule : builder.outerRule) { + rules.add(testRule); + } + rules.add(thisRule); + for (TestRule testRule : builder.innerRule) { + rules.add(testRule); + } + + RuleChain ruleChain = RuleChain.outerRule(rules.get(0)); + for (int i = 1; i < rules.size(); i++) { + ruleChain = ruleChain.around(rules.get(i)); } + + return ruleChain; } public DUnitTestRule() { StaticContext.logPerTestClass = Boolean.getBoolean(LOG_PER_TEST_CLASS_PROPERTY); + this.disconnectBeforeClass = false; + this.disconnectAfterClass = false; this.disconnectBefore = false; this.disconnectAfter = false; + this.ruleChain = RuleChain.outerRule(new ThisRule()); + } + + private class ThisRule implements TestRule, Serializable { + @Override + public Statement apply(final Statement base, final Description description) { + if (description.isTest()) { + starting(description); + return statement(base, description); + } else if (description.isSuite()) { + startingSuite(description); + return statementSuite(base, description); + } + return base; + } } @Override public Statement apply(final Statement base, final Description description) { - starting(description); - return statement(base); + return this.ruleChain.apply(base, description); + } + + /** + * Invoked when a suite is about to start + */ + protected void startingSuite(final Description description) { + this.className = description.getClassName(); + + boolean newTestClass = false; + if (StaticContext.testClassName != null && !this.className.equals(StaticContext.testClassName)) { + // new test class detected + newTestClass = true; + } + + if (newTestClass && StaticContext.logPerTestClass) { + disconnectAllFromDS(); + } + + StaticContext.testClassName = this.className; + } + + protected void beforeSuite() throws Throwable { + DUnitLauncher.launchIfNeeded(); + + setUpDistributedTestCase(); + + if (this.disconnectBeforeClass) { + disconnectAllFromDS(); + } + } + + protected void afterSuite() throws Throwable { + if (this.disconnectAfterClass) { + disconnectAllFromDS(); + } } /** @@ -119,7 +205,6 @@ public class DUnitTestRule implements TestRule, Serializable { } protected void before() throws Throwable { - System.out.println("KIRK DUnitTestRule before"); DUnitLauncher.launchIfNeeded(); setUpDistributedTestCase(); @@ -130,7 +215,6 @@ public class DUnitTestRule implements TestRule, Serializable { } protected void after() throws Throwable { - System.out.println("KIRK DUnitTestRule after"); if (this.disconnectAfter) { disconnectAllFromDS(); } @@ -158,7 +242,21 @@ public class DUnitTestRule implements TestRule, Serializable { return StaticContext.testMethodName; } - private Statement statement(final Statement base) { + private Statement statementSuite(final Statement base, final Description description) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + beforeSuite(); + try { + base.evaluate(); + } finally { + afterSuite(); + } + } + }; + } + + private Statement statement(final Statement base, final Description description) { return new Statement() { @Override public void evaluate() throws Throwable { @@ -615,9 +713,12 @@ public class DUnitTestRule implements TestRule, Serializable { public static class Builder { private boolean logPerTestMethod; private boolean logPerTestClass; + private boolean disconnectBeforeClass; + private boolean disconnectAfterClass; private boolean disconnectBefore; private boolean disconnectAfter; - private List ruleChain = new ArrayList(); + private final List outerRule = new ArrayList(); + private final List innerRule = new ArrayList(); protected Builder() {} @@ -640,19 +741,52 @@ public class DUnitTestRule implements TestRule, Serializable { this.logPerTestClass = logPerTestClass; return this; } + + /** + * DistributedSystem will be disconnected before each test class + */ + public Builder disconnectBeforeClass(final boolean disconnectBeforeClass) { + this.disconnectBeforeClass = disconnectBeforeClass; + return this; + } + /** + * DistributedSystem will be disconnected before each test method + */ public Builder disconnectBefore(final boolean disconnectBefore) { this.disconnectBefore = disconnectBefore; return this; } + /** + * DistributedSystem will be disconnected after each test class + */ + public Builder disconnectAfterClass(final boolean disconnectAfterClass) { + this.disconnectAfterClass = disconnectAfterClass; + return this; + } + + /** + * DistributedSystem will be disconnected after each test method + */ public Builder disconnectAfter(final boolean disconnectAfter) { this.disconnectAfter = disconnectAfter; return this; } - public Builder chainRule(final TestRule enclosedRule) { - this.ruleChain.add(enclosedRule); + /** + * Chain the specified TestRule around the DUnitTestRule + */ + public Builder outerRule(final TestRule testRule) { + this.outerRule.add(testRule); + return this; + } + + /** + * Chain the specified TestRule within the DUnitTestRule + */ + public Builder innerRule(final TestRule testRule) { + this.innerRule.add(testRule); return this; } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/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 deleted file mode 100755 index acf43b9..0000000 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/ThreadDump.java +++ /dev/null @@ -1,157 +0,0 @@ -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. - * - * These methods can be used directly: - * ThreadDump.dumpStack(...), however, they read better if they - * are referenced through static import: - * - *
- * import static com.gemstone.gemfire.test.dunit.ThreadDump.*;
- *    ...
- *    dumpStack(...);
- * 
- * - * 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/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Threads.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Threads.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Threads.java new file mode 100755 index 0000000..82022ea --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/Threads.java @@ -0,0 +1,161 @@ +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. + * + *

These methods can be used directly: + * ThreadDump.dumpStack(...), however, they read better if they + * are referenced through static import: + * + *

+ * import static com.gemstone.gemfire.test.dunit.ThreadDump.*;
+ *    ...
+ *    dumpStack(...);
+ * 
+ * + *

Extracted from DistributedTestCase + * + * @see VM + * @see Host + */ +@SuppressWarnings("serial") +public class Threads { + + protected Threads() { + } + + /** + * 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 thread thread to wait on + * @param timeoutMillis maximum time to wait + * @throws AssertionFailure if the thread does not terminate + */ + public static void join(final Thread thread, final long timeoutMillis) { + join(thread, timeoutMillis, new LocalLogWriter(LogWriterImpl.INFO_LEVEL, System.out)); + } + + /** + * Wait for a thread to join // TODO: remove LogWriter + * @param thread thread to wait on + * @param timeoutMillis maximum time to wait + * @throws AssertionFailure if the thread does not terminate + */ + public static void join(final Thread thread, final long timeoutMillis, final LogWriter logWriter) { + final long tilt = System.currentTimeMillis() + timeoutMillis; + final long incrementalWait = jitterInterval(timeoutMillis); + 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 (!thread.isAlive()) { + break; + } + try { + thread.join(incrementalWait); + } catch (InterruptedException e) { + fail("interrupted"); + } + if (System.currentTimeMillis() >= tilt) { + break; + } + } // for + if (thread.isAlive()) { + logWriter.info("HUNG THREAD"); + dumpStackTrace(thread, thread.getStackTrace(), logWriter); + dumpMyThreads(logWriter); + thread.interrupt(); // We're in trouble! + fail("Thread did not terminate after " + timeoutMillis + " ms: " + thread); + } + long elapsedMs = (System.currentTimeMillis() - start); + if (elapsedMs > 0) { + String msg = "Thread " + thread + " took " + + elapsedMs + + " ms to exit."; + logWriter.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/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedDisconnectRule.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedDisconnectRule.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedDisconnectRule.java new file mode 100755 index 0000000..fdb7990 --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedDisconnectRule.java @@ -0,0 +1,105 @@ +package com.gemstone.gemfire.test.dunit.rules; + +import static com.gemstone.gemfire.test.dunit.DUnitTestRule.*; + +import com.gemstone.gemfire.test.dunit.SerializableRunnable; + +@SuppressWarnings("serial") +public class DistributedDisconnectRule extends DistributedExternalResource { + + private final boolean disconnectBefore; + private final boolean disconnectAfter; + private final boolean disconnectBeforeClass; + private final boolean disconnectAfterClass; + + public static Builder builder() { + return new Builder(); + } + + public DistributedDisconnectRule(final Builder builder) { + this(new RemoteInvoker(), builder); + } + + public DistributedDisconnectRule(final RemoteInvoker invoker, final Builder builder) { + super(invoker); + this.disconnectBeforeClass = builder.disconnectBeforeClass; + this.disconnectAfterClass = builder.disconnectAfterClass; + this.disconnectBefore = builder.disconnectBefore; + this.disconnectAfter = builder.disconnectAfter; + } + + @Override + protected void before() throws Throwable { + if (this.disconnectBefore) { + invoker().invokeEverywhere(serializableRunnable()); + } + } + + @Override + protected void after() throws Throwable { + if (this.disconnectAfter) { + invoker().invokeEverywhere(serializableRunnable()); + } + } + + @Override + protected void beforeClass() throws Throwable { + if (this.disconnectBeforeClass) { + invoker().invokeEverywhere(serializableRunnable()); + } + } + + @Override + protected void afterClass() throws Throwable { + if (this.disconnectAfterClass) { + invoker().invokeEverywhere(serializableRunnable()); + } + } + + private static SerializableRunnable serializableRunnable() { + return new SerializableRunnable() { + @Override + public void run() { + disconnectFromDS(); + } + }; + } + + /** + * Builds an instance of DistributedDisconnectRule + * + * @author Kirk Lund + */ + public static class Builder { + private boolean disconnectBeforeClass; + private boolean disconnectAfterClass; + private boolean disconnectBefore; + private boolean disconnectAfter; + + public Builder() {} + + public Builder disconnectBeforeClass(final boolean disconnectBeforeClass) { + this.disconnectBeforeClass = disconnectBeforeClass; + return this; + } + + public Builder disconnectBefore(final boolean disconnectBefore) { + this.disconnectBefore = disconnectBefore; + return this; + } + + public Builder disconnectAfterClass(final boolean disconnectAfterClass) { + this.disconnectAfterClass = disconnectAfterClass; + return this; + } + + public Builder disconnectAfter(final boolean disconnectAfter) { + this.disconnectAfter = disconnectAfter; + return this; + } + + public DistributedDisconnectRule build() { + return new DistributedDisconnectRule(this); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedExternalResource.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedExternalResource.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedExternalResource.java new file mode 100755 index 0000000..2e1df0f --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedExternalResource.java @@ -0,0 +1,42 @@ +package com.gemstone.gemfire.test.dunit.rules; + +import com.gemstone.gemfire.test.junit.rules.SerializableExternalResource; + +@SuppressWarnings("serial") +public class DistributedExternalResource extends SerializableExternalResource { + + private final RemoteInvoker invoker; + + public DistributedExternalResource() { + this(new RemoteInvoker()); + } + + public DistributedExternalResource(final RemoteInvoker invoker) { + super(); + this.invoker = invoker; + } + + protected RemoteInvoker invoker() { + return this.invoker; + } + + @Override + protected void before() throws Throwable { + // do nothing + } + + @Override + protected void after() throws Throwable { + // do nothing + } + + @Override + protected void beforeClass() throws Throwable { + // do nothing + } + + @Override + protected void afterClass() throws Throwable { + // do nothing + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedRestoreSystemProperties.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedRestoreSystemProperties.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedRestoreSystemProperties.java index cea3dcd..c8d1cad 100755 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedRestoreSystemProperties.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/DistributedRestoreSystemProperties.java @@ -1,15 +1,14 @@ package com.gemstone.gemfire.test.dunit.rules; -import static com.gemstone.gemfire.test.dunit.Invoke.*; import static java.lang.System.getProperties; import static java.lang.System.setProperties; -import java.io.Serializable; import java.util.Properties; import org.junit.contrib.java.lang.system.RestoreSystemProperties; import com.gemstone.gemfire.test.dunit.SerializableRunnable; +import com.gemstone.gemfire.test.junit.rules.SerializableTestRule; /** * Distributed version of RestoreSystemProperties which affects all DUnit @@ -18,7 +17,7 @@ import com.gemstone.gemfire.test.dunit.SerializableRunnable; * @author Kirk Lund */ @SuppressWarnings("serial") -public class DistributedRestoreSystemProperties extends RestoreSystemProperties implements Serializable { +public class DistributedRestoreSystemProperties extends RestoreSystemProperties implements SerializableTestRule { private static volatile Properties originalProperties; @@ -33,10 +32,8 @@ public class DistributedRestoreSystemProperties extends RestoreSystemProperties this.invoker = invoker; } - @Override protected void before() throws Throwable { - System.out.println("KIRK DistributedRestoreSystemProperties before"); super.before(); this.invoker.remoteInvokeInEveryVMAndLocator(new SerializableRunnable() { @Override @@ -49,7 +46,6 @@ public class DistributedRestoreSystemProperties extends RestoreSystemProperties @Override protected void after() { - System.out.println("KIRK DistributedRestoreSystemProperties after"); super.after(); this.invoker.remoteInvokeInEveryVMAndLocator(new SerializableRunnable() { @Override @@ -59,11 +55,4 @@ public class DistributedRestoreSystemProperties extends RestoreSystemProperties } }); } - - public static class RemoteInvoker implements Serializable { - public void remoteInvokeInEveryVMAndLocator(final SerializableRunnable runnable) { - invokeInEveryVM(runnable); - invokeInLocator(runnable); - } - } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/RemoteInvoker.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/RemoteInvoker.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/RemoteInvoker.java new file mode 100755 index 0000000..e1d153b --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/RemoteInvoker.java @@ -0,0 +1,23 @@ +package com.gemstone.gemfire.test.dunit.rules; + +import static com.gemstone.gemfire.test.dunit.Invoke.invokeInEveryVM; +import static com.gemstone.gemfire.test.dunit.Invoke.invokeInLocator; + +import java.io.Serializable; + +import com.gemstone.gemfire.test.dunit.SerializableRunnable; + +@SuppressWarnings("serial") +public class RemoteInvoker implements Serializable { + + public void invokeEverywhere(final SerializableRunnable runnable) { + runnable.run(); + invokeInEveryVM(runnable); + invokeInLocator(runnable); + } + + public void remoteInvokeInEveryVMAndLocator(final SerializableRunnable runnable) { + invokeInEveryVM(runnable); + invokeInLocator(runnable); + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesDUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesDUnitTest.java index 9164413..c85a731 100755 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesDUnitTest.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesDUnitTest.java @@ -10,7 +10,6 @@ import java.util.Properties; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; -import org.junit.rules.RuleChain; import com.gemstone.gemfire.test.dunit.DUnitTestRule; import com.gemstone.gemfire.test.dunit.Host; @@ -33,14 +32,12 @@ public class DistributedRestoreSystemPropertiesDUnitTest implements Serializable private static final String NEW_VALUE = "NEW_VALUE"; @Rule - public transient RuleChain chain = RuleChain - .outerRule(new SetUp()) - .around(new Restore()) - .around(new Verify()) - .around(new DistributedRestoreSystemProperties()); - - @Rule - public final DUnitTestRule dunitTestRule = new DUnitTestRule(); + public final DUnitTestRule dunitTestRule = DUnitTestRule.builder() + .innerRule(new SetUp()) + .innerRule(new Restore()) + .innerRule(new Verify()) + .innerRule(new DistributedRestoreSystemProperties()) + .build(); @Test public void shouldRestoreInAllVMs() { http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesJUnitTest.java index edd2ad7..7e3f627 100755 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesJUnitTest.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/rules/tests/DistributedRestoreSystemPropertiesJUnitTest.java @@ -1,7 +1,6 @@ package com.gemstone.gemfire.test.dunit.rules.tests; import static com.gemstone.gemfire.test.junit.rules.tests.RunTest.*; -import static com.gemstone.gemfire.test.dunit.rules.DistributedRestoreSystemProperties.*; import static java.lang.System.*; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; @@ -17,6 +16,7 @@ import org.junit.runner.Result; import com.gemstone.gemfire.test.dunit.SerializableRunnable; import com.gemstone.gemfire.test.dunit.rules.DistributedRestoreSystemProperties; +import com.gemstone.gemfire.test.dunit.rules.RemoteInvoker; import com.gemstone.gemfire.test.junit.categories.UnitTest; /** @@ -70,5 +70,4 @@ public class DistributedRestoreSystemPropertiesJUnitTest { setProperty(SOME_PROPERTY, SOME_PROPERTY_NEW_VALUE); } } - } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestRuleChainDUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestRuleChainDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestRuleChainDUnitTest.java new file mode 100755 index 0000000..fa84c8d --- /dev/null +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/DUnitTestRuleChainDUnitTest.java @@ -0,0 +1,103 @@ +package com.gemstone.gemfire.test.dunit.tests; + +import static com.gemstone.gemfire.test.junit.rules.tests.RunTest.*; +import static org.assertj.core.api.Assertions.assertThat; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.runner.Result; + +import com.gemstone.gemfire.test.dunit.DUnitTestRule; +import com.gemstone.gemfire.test.junit.categories.DistributedTest; +import com.gemstone.gemfire.test.junit.rules.SerializableExternalResource; + +/** + * Distributed tests for chaining of rules to DUnitTestRule + * + * @author Kirk Lund + */ +@Category(DistributedTest.class) +@SuppressWarnings("serial") +public class DUnitTestRuleChainDUnitTest implements Serializable { + + private static enum Expected { + BEFORE_ONE_BEFORE, BEFORE_TWO_BEFORE, AFTER_ONE_BEFORE, AFTER_TWO_BEFORE, + TEST, + AFTER_TWO_AFTER, AFTER_ONE_AFTER, BEFORE_TWO_AFTER, BEFORE_ONE_AFTER }; + + private static List invocations = Collections.synchronizedList(new ArrayList()); + + @Test + public void chainedRulesShouldBeInvokedInCorrectOrder() { + Result result = runTest(DUnitTestWithChainedRules.class); + + assertThat(result.wasSuccessful()).isTrue(); + assertThat(invocations).as("Wrong order: " + invocations).containsExactly(Expected.values()); + } + + public static class DUnitTestWithChainedRules implements Serializable { + + @Rule + public final DUnitTestRule dunitTestRule = DUnitTestRule.builder() + .outerRule(new BeforeOne()) + .outerRule(new BeforeTwo()) + .innerRule(new AfterOne()) + .innerRule(new AfterTwo()) + .build(); + + @Test + public void doTest() { + invocations.add(Expected.TEST); + } + } + + public static class BeforeOne extends SerializableExternalResource { + @Override + protected void before() throws Throwable { + invocations.add(Expected.BEFORE_ONE_BEFORE); + } + @Override + protected void after() throws Throwable { + invocations.add(Expected.BEFORE_ONE_AFTER); + } + } + + public static class BeforeTwo extends SerializableExternalResource { + @Override + protected void before() throws Throwable { + invocations.add(Expected.BEFORE_TWO_BEFORE); + } + @Override + protected void after() throws Throwable { + invocations.add(Expected.BEFORE_TWO_AFTER); + } + } + + public static class AfterOne extends SerializableExternalResource { + @Override + protected void before() throws Throwable { + invocations.add(Expected.AFTER_ONE_BEFORE); + } + @Override + protected void after() throws Throwable { + invocations.add(Expected.AFTER_ONE_AFTER); + } + } + + public static class AfterTwo extends SerializableExternalResource { + @Override + protected void before() throws Throwable { + invocations.add(Expected.AFTER_TWO_BEFORE); + } + @Override + protected void after() throws Throwable { + invocations.add(Expected.AFTER_TWO_AFTER); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/LogPerTestMethodDUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/LogPerTestMethodDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/LogPerTestMethodDUnitTest.java index fda1d5a..9d54f6b 100755 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/LogPerTestMethodDUnitTest.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/LogPerTestMethodDUnitTest.java @@ -12,7 +12,6 @@ import org.junit.experimental.categories.Category; import com.gemstone.gemfire.distributed.internal.DistributionConfig; import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; import com.gemstone.gemfire.test.dunit.DUnitTestRule; -import com.gemstone.gemfire.test.dunit.SerializableRunnable; import com.gemstone.gemfire.test.junit.categories.DistributedTest; @Category(DistributedTest.class) @@ -42,15 +41,4 @@ public class LogPerTestMethodDUnitTest implements Serializable { assertThat(mySystem.getProperties()).containsEntry(DistributionConfig.LOG_FILE_NAME, getUniqueName() + ".log"); assertThat(mySystem.getProperties()).containsEntry(DistributionConfig.STATISTIC_ARCHIVE_FILE_NAME, getUniqueName() + ".gfs"); } - - public static class InnerClass { - public static SerializableRunnable staticSerializableRunnable() { - return new SerializableRunnable() { - @Override - public void run() { - System.out.println("printing from static SerializableRunnable"); - } - }; - } - } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java index 3759cf9..6a0a4ed 100755 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/dunit/tests/MyTestSuite.java @@ -6,13 +6,16 @@ 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.dunit.rules.tests.DistributedRestoreSystemPropertiesDUnitTest; import com.gemstone.gemfire.test.examples.CatchExceptionExampleDUnitTest; @RunWith(Suite.class) @Suite.SuiteClasses({ BasicDUnitTest.class, + DistributedRestoreSystemPropertiesDUnitTest.class, DistributedTestNameDUnitTest.class, DistributedTestNameWithRuleDUnitTest.class, + DUnitTestRuleChainDUnitTest.class, SerializableTemporaryFolderDUnitTest.class, SerializableTestNameDUnitTest.class, SerializableTestWatcherDUnitTest.class, http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleDUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleDUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleDUnitTest.java index 04a45c5..4693c01 100755 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleDUnitTest.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleDUnitTest.java @@ -1,7 +1,7 @@ package com.gemstone.gemfire.test.examples; import static com.googlecode.catchexception.CatchException.*; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.StrictAssertions.*; import java.io.Serializable; http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleJUnitTest.java ---------------------------------------------------------------------- diff --git a/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleJUnitTest.java b/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleJUnitTest.java index abfe0ce..2a1ba26 100755 --- a/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleJUnitTest.java +++ b/gemfire-core/src/test/java/com/gemstone/gemfire/test/examples/CatchExceptionExampleJUnitTest.java @@ -52,7 +52,7 @@ public class CatchExceptionExampleJUnitTest { when(myList).get(1); // then: we expect an IndexOutOfBoundsException - then(caughtException()) + then((Exception)caughtException()) .isInstanceOf(IndexOutOfBoundsException.class) .hasMessage("Index: 1, Size: 0") .hasNoCause(); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableExternalResource.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableExternalResource.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableExternalResource.java index 7cfbc96..d4715b6 100755 --- a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableExternalResource.java +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableExternalResource.java @@ -1,23 +1,28 @@ package com.gemstone.gemfire.test.junit.rules; -import java.io.Serializable; - -import org.junit.rules.TestRule; import org.junit.runner.Description; import org.junit.runners.model.Statement; /** * Serializable version of ExternalResource JUnit Rule. JUnit lifecycle is not - * executed in remote JVMs. The after() callback has throws-clause that matches - * before(). + * executed in remote JVMs. The after() callback has a throws-clause + * that matches before(). + * + * Implementation copied from org.junit.rules.ExternalResource. * * @author Kirk Lund */ @SuppressWarnings("serial") -public abstract class SerializableExternalResource implements Serializable, TestRule { +public abstract class SerializableExternalResource implements SerializableTestRule { - public Statement apply(Statement base, Description description) { - return statement(base); + @Override + public Statement apply(final Statement base, final Description description) { + if (description.isTest()) { + return statement(base); + } else if (description.isSuite()) { + return statementClass(base); + } + return base; } private Statement statement(final Statement base) { @@ -34,6 +39,20 @@ public abstract class SerializableExternalResource implements Serializable, Test }; } + private Statement statementClass(final Statement base) { + return new Statement() { + @Override + public void evaluate() throws Throwable { + beforeClass(); + try { + base.evaluate(); + } finally { + afterClass(); + } + } + }; + } + /** * Override to set up your specific external resource. * @@ -45,8 +64,28 @@ public abstract class SerializableExternalResource implements Serializable, Test /** * Override to tear down your specific external resource. + * + * @throws Throwable if teardown fails (which will disable {@code after} + */ + protected void after() throws Throwable { + // do nothing + } + + /** + * Override to set up your specific external resource. + * + * @throws Throwable if setup fails (which will disable {@code after} + */ + protected void beforeClass() throws Throwable { + // do nothing + } + + /** + * Override to tear down your specific external resource. + * + * @throws Throwable if teardown fails (which will disable {@code after} */ - protected void after() throws Throwable { // ExternalResource is missing this throws-clause + protected void afterClass() throws Throwable { // do nothing } } http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableRuleChain.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableRuleChain.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableRuleChain.java new file mode 100755 index 0000000..b5dfdd4 --- /dev/null +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableRuleChain.java @@ -0,0 +1,103 @@ +package com.gemstone.gemfire.test.junit.rules; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; + +/** + * Serializable version of TemporaryFolder JUnit Rule. JUnit lifecycle is not + * executed in remote JVMs. + * + * Implementation copied from org.junit.rules.RuleChain. + * + * The SerializableRuleChain rule allows ordering of TestRules. You create a + * {@code RuleChain} with {@link #outerRule(TestRule)} and subsequent calls of + * {@link #around(TestRule)}: + * + *

+ * public static class UseRuleChain {
+ *  @Rule
+ *  public RuleChain chain= RuleChain
+ *                         .outerRule(new LoggingRule("outer rule")
+ *                         .around(new LoggingRule("middle rule")
+ *                         .around(new LoggingRule("inner rule");
+ *
+ *  @Test
+ *  public void example() {
+ *    assertTrue(true);
+ *     }
+ * }
+ * 
+ * + * writes the log + * + *
+ * starting outer rule
+ * starting middle rule
+ * starting inner rule
+ * finished inner rule
+ * finished middle rule
+ * finished outer rule
+ * 
+ * + * @author Kirk Lund + */ +@SuppressWarnings("serial") +public class SerializableRuleChain implements SerializableTestRule { + private static final SerializableRuleChain EMPTY_CHAIN = new SerializableRuleChain(Collections.emptyList()); + + private transient List rulesStartingWithInnerMost; + + /** + * Returns a {@code SerializableRuleChain} without a {@link TestRule}. This method may + * be the starting point of a {@code SerializableRuleChain}. + * + * @return a {@code SerializableRuleChain} without a {@link TestRule}. + */ + public static SerializableRuleChain emptyRuleChain() { + return EMPTY_CHAIN; + } + + /** + * Returns a {@code SerializableRuleChain} with a single {@link TestRule}. This method + * is the usual starting point of a {@code SerializableRuleChain}. + * + * @param outerRule the outer rule of the {@code SerializableRuleChain}. + * @return a {@code SerializableRuleChain} with a single {@link TestRule}. + */ + public static SerializableRuleChain outerRule(TestRule outerRule) { + return emptyRuleChain().around(outerRule); + } + + private SerializableRuleChain(List rules) { + this.rulesStartingWithInnerMost = rules; + } + + /** + * Create a new {@code SerializableRuleChain}, which encloses the {@code nextRule} with + * the rules of the current {@code SerializableRuleChain}. + * + * @param enclosedRule the rule to enclose. + * @return a new {@code SerializableRuleChain}. + */ + public SerializableRuleChain around(TestRule enclosedRule) { + List rulesOfNewChain = new ArrayList(); + rulesOfNewChain.add(enclosedRule); + rulesOfNewChain.addAll(rulesStartingWithInnerMost); + return new SerializableRuleChain(rulesOfNewChain); + } + + /** + * {@inheritDoc} + */ + public Statement apply(Statement base, Description description) { + for (TestRule each : rulesStartingWithInnerMost) { + base = each.apply(base, description); + } + return base; + } +} http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTemporaryFolder.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTemporaryFolder.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTemporaryFolder.java index ea335eb..15a0a30 100755 --- a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTemporaryFolder.java +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTemporaryFolder.java @@ -3,7 +3,6 @@ package com.gemstone.gemfire.test.junit.rules; import java.io.File; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.io.Serializable; import java.lang.reflect.Field; import org.junit.rules.TemporaryFolder; @@ -15,7 +14,7 @@ import org.junit.rules.TemporaryFolder; * @author Kirk Lund */ @SuppressWarnings("serial") -public class SerializableTemporaryFolder extends TemporaryFolder implements Serializable { +public class SerializableTemporaryFolder extends TemporaryFolder implements SerializableTestRule { private void writeObject(final ObjectOutputStream out) throws Exception { writeParentFolder(out); http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/435dc63c/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestName.java ---------------------------------------------------------------------- diff --git a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestName.java b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestName.java index d82d0d5..9813fd0 100755 --- a/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestName.java +++ b/gemfire-junit/src/test/java/com/gemstone/gemfire/test/junit/rules/SerializableTestName.java @@ -2,7 +2,6 @@ package com.gemstone.gemfire.test.junit.rules; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.io.Serializable; import java.lang.reflect.Field; import org.junit.rules.TestName; @@ -14,7 +13,7 @@ import org.junit.rules.TestName; * @author Kirk Lund */ @SuppressWarnings("serial") -public class SerializableTestName extends TestName implements Serializable { +public class SerializableTestName extends TestName implements SerializableTestRule { private void writeObject(final ObjectOutputStream out) throws Exception { writeName(out);