This is an automated email from the ASF dual-hosted git repository.
klund pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git
The following commit(s) were added to refs/heads/develop by this push:
new bd1e149 GEODE-5644: Add new DistributedReference JUnit Rule
new 24bf1ea Merge pull request #4401 from
kirklund/GEODE-5644-DistributedReference
bd1e149 is described below
commit bd1e1491618bef2250ec1e382d3a03c74aa345da
Author: Kirk Lund <[email protected]>
AuthorDate: Fri Oct 4 14:22:12 2019 -0700
GEODE-5644: Add new DistributedReference JUnit Rule
JUnit Rule that provides a static reference in every distributed test
VMs including the main JUnit controller VM. If the referenced value is
is an AutoCloseable or Closeable then it will be auto-closed in every
VM during tear down.
If the referenced value is not an AutoCloseable or Closeable, the
DistributedReference will use reflection to invoke any method named
close or disconnect regardless of what interfaces are implemented.
If the referenced value is null in any VM then it will be ignored in
that VM during tear down.
To disable auto-close, simply specify autoClose(false).
See the javadocs on DistributedReference for more info.
---
.../DistributedReferenceCacheExampleTest.java | 64 ++
...ributedReferenceLocatorLauncherExampleTest.java | 95 +++
...tributedReferenceServerLauncherExampleTest.java | 82 +++
.../DistributedReferenceSystemExampleTest.java | 63 ++
.../rules/tests/DistributedReferenceTest.java | 653 +++++++++++++++++++++
.../test/dunit/rules/DistributedReference.java | 215 +++++++
6 files changed, 1172 insertions(+)
diff --git
a/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceCacheExampleTest.java
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceCacheExampleTest.java
new file mode 100644
index 0000000..f7f2df0
--- /dev/null
+++
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceCacheExampleTest.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.test.dunit.examples;
+
+import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
+import static org.apache.geode.test.dunit.VM.getController;
+import static org.apache.geode.test.dunit.VM.getVM;
+import static org.apache.geode.test.dunit.VM.toArray;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.test.dunit.DistributedTestUtils;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.rules.DistributedReference;
+
+@SuppressWarnings("serial")
+public class DistributedReferenceCacheExampleTest implements Serializable {
+
+ @Rule
+ public DistributedReference<Cache> cache = new DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ Properties configProperties = new Properties();
+ configProperties.setProperty(LOCATORS, DistributedTestUtils.getLocators());
+
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ cache.set(new CacheFactory(configProperties).create());
+ });
+ }
+ }
+
+ @Test
+ public void eachVmHasItsOwnCache() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ assertThat(cache.get()).isInstanceOf(Cache.class);
+ });
+ }
+ }
+}
diff --git
a/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceLocatorLauncherExampleTest.java
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceLocatorLauncherExampleTest.java
new file mode 100644
index 0000000..21dc524
--- /dev/null
+++
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceLocatorLauncherExampleTest.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+package org.apache.geode.test.dunit.examples;
+
+import static
org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_PORT;
+import static
org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_PORT;
+import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
+import static org.apache.geode.test.dunit.DistributedTestUtils.getLocatorPort;
+import static org.apache.geode.test.dunit.VM.getController;
+import static org.apache.geode.test.dunit.VM.getHostName;
+import static org.apache.geode.test.dunit.VM.getVM;
+import static org.apache.geode.test.dunit.VM.getVMId;
+import static org.apache.geode.test.dunit.VM.toArray;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.Serializable;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.geode.distributed.LocatorLauncher;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.internal.AvailablePortHelper;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.rules.DistributedReference;
+import
org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder;
+
+@SuppressWarnings("serial")
+public class DistributedReferenceLocatorLauncherExampleTest implements
Serializable {
+
+ @Rule
+ public DistributedReference<LocatorLauncher> locatorLauncher = new
DistributedReference<>();
+
+ @Rule
+ public SerializableTemporaryFolder temporaryFolder = new
SerializableTemporaryFolder();
+
+ @Before
+ public void setUp() {
+ String hostName = getHostName();
+ int[] randomPorts = AvailablePortHelper.getRandomAvailableTCPPorts(5);
+
+ StringBuilder locators = new StringBuilder()
+
.append(hostName).append('[').append(getLocatorPort()).append(']').append(',')
+
.append(hostName).append('[').append(randomPorts[0]).append(']').append(',')
+
.append(hostName).append('[').append(randomPorts[1]).append(']').append(',')
+
.append(hostName).append('[').append(randomPorts[2]).append(']').append(',')
+
.append(hostName).append('[').append(randomPorts[3]).append(']').append(',')
+ .append(hostName).append('[').append(randomPorts[4]).append(']');
+
+ int index = 0;
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ int whichPort = index++;
+ vm.invoke(() -> {
+ String name = getClass().getSimpleName() + "-vm-" + getVMId();
+ LocatorLauncher locatorLauncher = new LocatorLauncher.Builder()
+
.setWorkingDirectory(temporaryFolder.newFolder(name).getAbsolutePath())
+ .setMemberName(name)
+ .setPort(randomPorts[whichPort])
+ .set(LOCATORS, locators.toString())
+ .set(HTTP_SERVICE_PORT, "0")
+ .set(JMX_MANAGER_PORT, "0")
+ .build();
+ locatorLauncher.start();
+ this.locatorLauncher.set(locatorLauncher);
+ });
+ }
+ }
+
+ @Test
+ public void eachVmHasItsOwnLocatorLauncher() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ assertThat(locatorLauncher.get()).isInstanceOf(LocatorLauncher.class);
+
+ InternalCache cache = (InternalCache) locatorLauncher.get().getCache();
+ InternalDistributedSystem system =
cache.getInternalDistributedSystem();
+ assertThat(system.getAllOtherMembers()).hasSize(5);
+ });
+ }
+ }
+}
diff --git
a/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceServerLauncherExampleTest.java
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceServerLauncherExampleTest.java
new file mode 100644
index 0000000..7b18a2f
--- /dev/null
+++
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceServerLauncherExampleTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license
+ * agreements. See the NOTICE file distributed with this work for additional
information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache
License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express
+ * or implied. See the License for the specific language governing permissions
and limitations under
+ * the License.
+ */
+package org.apache.geode.test.dunit.examples;
+
+import static
org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_PORT;
+import static
org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_PORT;
+import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
+import static org.apache.geode.test.dunit.VM.getController;
+import static org.apache.geode.test.dunit.VM.getVM;
+import static org.apache.geode.test.dunit.VM.getVMId;
+import static org.apache.geode.test.dunit.VM.toArray;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.Serializable;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.geode.distributed.ServerLauncher;
+import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.internal.cache.InternalCache;
+import org.apache.geode.test.dunit.DistributedTestUtils;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.rules.DistributedReference;
+import
org.apache.geode.test.junit.rules.serializable.SerializableTemporaryFolder;
+
+@SuppressWarnings("serial")
+public class DistributedReferenceServerLauncherExampleTest implements
Serializable {
+
+ @Rule
+ public DistributedReference<ServerLauncher> serverLauncher = new
DistributedReference<>();
+
+ @Rule
+ public SerializableTemporaryFolder temporaryFolder = new
SerializableTemporaryFolder();
+
+ @Before
+ public void setUp() {
+ String locators = DistributedTestUtils.getLocators();
+
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ String name = getClass().getSimpleName() + "-vm-" + getVMId();
+ ServerLauncher serverLauncher = new ServerLauncher.Builder()
+
.setWorkingDirectory(temporaryFolder.newFolder(name).getAbsolutePath())
+ .setMemberName(name)
+ .setDisableDefaultServer(true)
+ .set(LOCATORS, locators)
+ .set(HTTP_SERVICE_PORT, "0")
+ .set(JMX_MANAGER_PORT, "0")
+ .build();
+ serverLauncher.start();
+ this.serverLauncher.set(serverLauncher);
+ });
+ }
+ }
+
+ @Test
+ public void eachVmHasItsOwnLocatorLauncher() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ assertThat(serverLauncher.get()).isInstanceOf(ServerLauncher.class);
+
+ InternalCache cache = (InternalCache) serverLauncher.get().getCache();
+ InternalDistributedSystem system =
cache.getInternalDistributedSystem();
+ assertThat(system.getAllOtherMembers()).hasSize(5);
+ });
+ }
+ }
+}
diff --git
a/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceSystemExampleTest.java
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceSystemExampleTest.java
new file mode 100644
index 0000000..3e3e4ca
--- /dev/null
+++
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/examples/DistributedReferenceSystemExampleTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.test.dunit.examples;
+
+import static org.apache.geode.distributed.ConfigurationProperties.LOCATORS;
+import static org.apache.geode.test.dunit.VM.getController;
+import static org.apache.geode.test.dunit.VM.getVM;
+import static org.apache.geode.test.dunit.VM.toArray;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.Serializable;
+import java.util.Properties;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.geode.distributed.DistributedSystem;
+import org.apache.geode.test.dunit.DistributedTestUtils;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.rules.DistributedReference;
+
+@SuppressWarnings("serial")
+public class DistributedReferenceSystemExampleTest implements Serializable {
+
+ @Rule
+ public DistributedReference<DistributedSystem> system = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ Properties configProperties = new Properties();
+ configProperties.setProperty(LOCATORS, DistributedTestUtils.getLocators());
+
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ system.set(DistributedSystem.connect(configProperties));
+ });
+ }
+ }
+
+ @Test
+ public void eachVmHasItsOwnSystemConnection() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ assertThat(system.get()).isInstanceOf(DistributedSystem.class);
+ });
+ }
+ }
+}
diff --git
a/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/rules/tests/DistributedReferenceTest.java
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/rules/tests/DistributedReferenceTest.java
new file mode 100644
index 0000000..21989ba
--- /dev/null
+++
b/geode-dunit/src/distributedTest/java/org/apache/geode/test/dunit/rules/tests/DistributedReferenceTest.java
@@ -0,0 +1,653 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.test.dunit.rules.tests;
+
+import static org.apache.geode.test.dunit.VM.getController;
+import static org.apache.geode.test.dunit.VM.getVM;
+import static org.apache.geode.test.dunit.VM.toArray;
+import static
org.apache.geode.test.junit.runners.TestRunner.runTestWithValidation;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.io.Closeable;
+import java.io.Serializable;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.rules.DistributedReference;
+import org.apache.geode.test.dunit.rules.DistributedRule;
+
+@SuppressWarnings({"serial", "unused"})
+public class DistributedReferenceTest {
+
+ @Rule
+ public DistributedRule distributedRule = new DistributedRule();
+
+ @Test
+ public void accessesAutoCloseableInLocalVm() {
+ runTestWithValidation(SetAutoCloseableInLocalVm.class);
+ }
+
+ @Test
+ public void closesAutoCloseableInLocalVm() throws Exception {
+ runTestWithValidation(SetAutoCloseableInLocalVm.class);
+
+ verify(SetAutoCloseableInLocalVm.autoCloseable).close();
+ }
+
+ @Test
+ public void doesNotAutoCloseIfAutoCloseIsFalse() throws Exception {
+ runTestWithValidation(DisableAutoCloseInLocalVm.class);
+
+ verify(DisableAutoCloseInLocalVm.autoCloseable, times(0)).close();
+ }
+
+ @Test
+ public void accessesAutoCloseableInRemoteVm() {
+ runTestWithValidation(SetAutoCloseableInRemoteVm.class);
+ }
+
+ @Test
+ public void closesAutoCloseableInRemoteVm() {
+ runTestWithValidation(SetAutoCloseableInRemoteVm.class);
+
+ getVM(0).invoke(() ->
verify(SetAutoCloseableInRemoteVm.autoCloseable).close());
+ }
+
+ @Test
+ public void accessesAutoCloseableInEachVm() {
+ runTestWithValidation(SetAutoCloseableInEachVm.class);
+ }
+
+ @Test
+ public void closesAutoCloseableInEachVm() {
+ runTestWithValidation(SetAutoCloseableInEachVm.class);
+
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ verify(SetAutoCloseableInEachVm.autoCloseable).close();
+ });
+ }
+ }
+
+ @Test
+ public void accessesCloseableInLocalVm() {
+ runTestWithValidation(SetCloseableInLocalVm.class);
+ }
+
+ @Test
+ public void closesCloseableInLocalVm() throws Exception {
+ runTestWithValidation(SetCloseableInLocalVm.class);
+
+ verify(SetCloseableInLocalVm.closeable).close();
+ }
+
+ @Test
+ public void accessesCloseableInRemoteVm() {
+ runTestWithValidation(SetCloseableInRemoteVm.class);
+ }
+
+ @Test
+ public void closesCloseableInRemoteVm() {
+ runTestWithValidation(SetCloseableInRemoteVm.class);
+
+ getVM(0).invoke(() -> verify(SetCloseableInRemoteVm.closeable).close());
+ }
+
+ @Test
+ public void accessesCloseableInEachVm() {
+ runTestWithValidation(SetCloseableInEachVm.class);
+ }
+
+ @Test
+ public void closesCloseableInEachVm() {
+ runTestWithValidation(SetCloseableInEachVm.class);
+
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ verify(SetCloseableInEachVm.closeable).close();
+ });
+ }
+ }
+
+ @Test
+ public void accessesWithCloseInLocalVm() {
+ runTestWithValidation(SetWithCloseInLocalVm.class);
+ }
+
+ @Test
+ public void closesWithCloseInLocalVm() {
+ runTestWithValidation(SetWithCloseInLocalVm.class);
+
+ verify(SetWithCloseInLocalVm.withClose).close();
+ }
+
+ @Test
+ public void accessesWithCloseInRemoteVm() {
+ runTestWithValidation(SetWithCloseInRemoteVm.class);
+ }
+
+ @Test
+ public void closesWithCloseInRemoteVm() {
+ runTestWithValidation(SetWithCloseInRemoteVm.class);
+
+ getVM(0).invoke(() -> verify(SetWithCloseInRemoteVm.withClose).close());
+ }
+
+ @Test
+ public void accessesWithCloseInEachVm() {
+ runTestWithValidation(SetWithCloseInEachVm.class);
+ }
+
+ @Test
+ public void closesWithCloseInEachVm() {
+ runTestWithValidation(SetWithCloseInEachVm.class);
+
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ verify(SetWithCloseInEachVm.withClose).close();
+ });
+ }
+ }
+
+ @Test
+ public void accessesWithDisconnectInLocalVm() {
+ runTestWithValidation(SetWithDisconnectInLocalVm.class);
+ }
+
+ @Test
+ public void disconnectsWithDisconnectInLocalVm() {
+ runTestWithValidation(SetWithDisconnectInLocalVm.class);
+
+ verify(SetWithDisconnectInLocalVm.withDisconnect).disconnect();
+ }
+
+ @Test
+ public void accessesWithDisconnectInRemoteVm() {
+ runTestWithValidation(SetWithDisconnectInRemoteVm.class);
+ }
+
+ @Test
+ public void disconnectsWithDisconnectInRemoteVm() {
+ runTestWithValidation(SetWithDisconnectInRemoteVm.class);
+
+ getVM(0).invoke(() ->
verify(SetWithDisconnectInRemoteVm.withDisconnect).disconnect());
+ }
+
+ @Test
+ public void accessesWithDisconnectInEachVm() {
+ runTestWithValidation(SetWithDisconnectInEachVm.class);
+ }
+
+ @Test
+ public void disconnectsWithDisconnectInEachVm() {
+ runTestWithValidation(SetWithDisconnectInEachVm.class);
+
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ verify(SetWithDisconnectInEachVm.withDisconnect).disconnect();
+ });
+ }
+ }
+
+ public static class SetAutoCloseableInLocalVm implements Serializable {
+
+ private static AutoCloseable autoCloseable;
+
+ @Rule
+ public DistributedReference<AutoCloseable> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ autoCloseable = mock(AutoCloseable.class);
+ reference.set(autoCloseable);
+ }
+
+ @Test
+ public void hasReferenceInLocalVm() {
+ assertThat(reference.get()).isSameAs(autoCloseable);
+ }
+ }
+
+ public static class DisableAutoCloseInLocalVm implements Serializable {
+
+ private static AutoCloseable autoCloseable;
+
+ @Rule
+ public DistributedReference<AutoCloseable> reference =
+ new DistributedReference<AutoCloseable>().autoClose(false);
+
+ @Before
+ public void setUp() {
+ autoCloseable = mock(AutoCloseable.class);
+ reference.set(autoCloseable);
+ }
+
+ @Test
+ public void hasReferenceInLocalVm() {
+ assertThat(reference.get()).isSameAs(autoCloseable);
+ }
+ }
+
+ public static class SetAutoCloseableInRemoteVm implements Serializable {
+
+ private static AutoCloseable autoCloseable;
+
+ @Rule
+ public DistributedReference<AutoCloseable> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ VM vm = getVM(0);
+ vm.invoke(() -> {
+ autoCloseable = mock(AutoCloseable.class, "AutoCloseable in VM-" +
vm.getId());
+ reference.set(autoCloseable);
+ });
+ }
+
+ @Test
+ public void hasAutoCloseableInRemoteVm() {
+ getVM(0).invoke(() -> {
+ assertThat(reference.get()).isSameAs(autoCloseable);
+ });
+ }
+ }
+
+ public static class SetAutoCloseableInEachVm implements Serializable {
+
+ private static AutoCloseable autoCloseable;
+
+ @Rule
+ public DistributedReference<AutoCloseable> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ autoCloseable = mock(AutoCloseable.class, "AutoCloseable in VM-" +
vm.getId());
+ reference.set(autoCloseable);
+ });
+ }
+ }
+
+ @Test
+ public void hasAutoCloseableInEachVm() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ assertThat(reference.get()).isSameAs(autoCloseable);
+ assertThat(reference.get().toString()).isEqualTo("AutoCloseable in
VM-" + vm.getId());
+ });
+ }
+ }
+ }
+
+ public static class SetCloseableInLocalVm implements Serializable {
+
+ private static Closeable closeable;
+
+ @Rule
+ public DistributedReference<Closeable> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ closeable = mock(Closeable.class);
+ reference.set(closeable);
+ }
+
+ @Test
+ public void hasCloseableInLocalVm() {
+ assertThat(reference.get()).isSameAs(closeable);
+ }
+ }
+
+ public static class SetCloseableInRemoteVm implements Serializable {
+
+ private static Closeable closeable;
+
+ @Rule
+ public DistributedReference<Closeable> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ VM vm = getVM(0);
+ vm.invoke(() -> {
+ closeable = mock(Closeable.class, "Closeable in VM-" + vm.getId());
+ reference.set(closeable);
+ });
+ }
+
+ @Test
+ public void hasCloseableInRemoteVm() {
+ getVM(0).invoke(() -> {
+ assertThat(reference.get()).isSameAs(closeable);
+ });
+ }
+ }
+
+ public static class SetCloseableInEachVm implements Serializable {
+
+ private static Closeable closeable;
+
+ @Rule
+ public DistributedReference<Closeable> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ closeable = mock(Closeable.class, "Closeable in VM-" + vm.getId());
+ reference.set(closeable);
+ });
+ }
+ }
+
+ @Test
+ public void hasCloseableInEachVm() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ assertThat(reference.get()).isSameAs(closeable);
+ assertThat(reference.get().toString()).isEqualTo("Closeable in VM-"
+ vm.getId());
+ });
+ }
+ }
+ }
+
+ public static class SetWithCloseInLocalVm implements Serializable {
+
+ private static WithClose withClose;
+
+ @Rule
+ public DistributedReference<WithClose> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ withClose = spy(new WithClose());
+ reference.set(withClose);
+ }
+
+ @Test
+ public void hasWithCloseInLocalVm() {
+ assertThat(reference.get()).isSameAs(withClose);
+ }
+ }
+
+ public static class SetWithCloseInRemoteVm implements Serializable {
+
+ private static WithClose withClose;
+
+ @Rule
+ public DistributedReference<WithClose> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ VM vm = getVM(0);
+ vm.invoke(() -> {
+ withClose = spy(new WithClose("WithClose in VM-" + vm.getId()));
+ reference.set(withClose);
+ });
+ }
+
+ @Test
+ public void hasWithCloseInRemoteVm() {
+ getVM(0).invoke(() -> {
+ assertThat(reference.get()).isSameAs(withClose);
+ });
+ }
+ }
+
+ public static class SetWithCloseInEachVm implements Serializable {
+
+ private static WithClose withClose;
+
+ @Rule
+ public DistributedReference<WithClose> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ withClose = spy(new WithClose("WithClose in VM-" + vm.getId()));
+ reference.set(withClose);
+ });
+ }
+ }
+
+ @Test
+ public void hasCloseableInEachVm() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ assertThat(reference.get()).isSameAs(withClose);
+ assertThat(reference.get().toString()).isEqualTo("WithClose in VM-"
+ vm.getId());
+ });
+ }
+ }
+ }
+
+ public static class SetWithDisconnectInLocalVm implements Serializable {
+
+ private static WithDisconnect withDisconnect;
+
+ @Rule
+ public DistributedReference<WithDisconnect> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ withDisconnect = spy(new WithDisconnect());
+ reference.set(withDisconnect);
+ }
+
+ @Test
+ public void hasWithDisconnectInLocalVm() {
+ assertThat(reference.get()).isSameAs(withDisconnect);
+ }
+ }
+
+ public static class SetWithDisconnectInRemoteVm implements Serializable {
+
+ private static WithDisconnect withDisconnect;
+
+ @Rule
+ public DistributedReference<WithDisconnect> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ VM vm = getVM(0);
+ vm.invoke(() -> {
+ withDisconnect = spy(new WithDisconnect("WithDisconnect in VM-" +
vm.getId()));
+ reference.set(withDisconnect);
+ });
+ }
+
+ @Test
+ public void hasWithDisconnectInRemoteVm() {
+ getVM(0).invoke(() -> {
+ assertThat(reference.get()).isSameAs(withDisconnect);
+ });
+ }
+ }
+
+ public static class SetWithDisconnectInEachVm implements Serializable {
+
+ private static WithDisconnect withDisconnect;
+
+ @Rule
+ public DistributedReference<WithDisconnect> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ withDisconnect = spy(new WithDisconnect("WithDisconnect in VM-" +
vm.getId()));
+ reference.set(withDisconnect);
+ });
+ }
+ }
+
+ @Test
+ public void hasWithDisconnectInEachVm() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ assertThat(reference.get()).isSameAs(withDisconnect);
+ assertThat(reference.get().toString()).isEqualTo("WithDisconnect in
VM-" + vm.getId());
+ });
+ }
+ }
+ }
+
+ public static class SetWithStopInLocalVm implements Serializable {
+
+ private static WithStop withStop;
+
+ @Rule
+ public DistributedReference<WithStop> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ withStop = spy(new WithStop());
+ reference.set(withStop);
+ }
+
+ @Test
+ public void hasWithStopInLocalVm() {
+ assertThat(reference.get()).isSameAs(withStop);
+ }
+ }
+
+ public static class SetWithStopInRemoteVm implements Serializable {
+
+ private static WithStop withStop;
+
+ @Rule
+ public DistributedReference<WithStop> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ VM vm = getVM(0);
+ vm.invoke(() -> {
+ withStop = spy(new WithStop("WithStop in VM-" + vm.getId()));
+ reference.set(withStop);
+ });
+ }
+
+ @Test
+ public void hasWithStopInRemoteVm() {
+ getVM(0).invoke(() -> {
+ assertThat(reference.get()).isSameAs(withStop);
+ });
+ }
+ }
+
+ public static class SetWithStopInEachVm implements Serializable {
+
+ private static WithStop withStop;
+
+ @Rule
+ public DistributedReference<WithStop> reference = new
DistributedReference<>();
+
+ @Before
+ public void setUp() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ withStop = spy(new WithStop("WithStop in VM-" + vm.getId()));
+ reference.set(withStop);
+ });
+ }
+ }
+
+ @Test
+ public void hasWithStopInEachVm() {
+ for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ vm.invoke(() -> {
+ assertThat(reference.get()).isSameAs(withStop);
+ assertThat(reference.get().toString()).isEqualTo("WithStop in VM-" +
vm.getId());
+ });
+ }
+ }
+ }
+
+ public static class WithClose {
+
+ private final String value;
+
+ WithClose() {
+ this("WithClose");
+ }
+
+ WithClose(String value) {
+ this.value = value;
+ }
+
+ public void close() {
+ // nothing
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+ public static class WithDisconnect {
+
+ private final String value;
+
+ WithDisconnect() {
+ this("WithDisconnect");
+ }
+
+ WithDisconnect(String value) {
+ this.value = value;
+ }
+
+ public void disconnect() {
+ // nothing
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+
+ public static class WithStop {
+
+ private final String value;
+
+ WithStop() {
+ this("WithStop");
+ }
+
+ WithStop(String value) {
+ this.value = value;
+ }
+
+ public void stop() {
+ // nothing
+ }
+
+ @Override
+ public String toString() {
+ return value;
+ }
+ }
+}
diff --git
a/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/DistributedReference.java
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/DistributedReference.java
new file mode 100644
index 0000000..3f2f9bb
--- /dev/null
+++
b/geode-dunit/src/main/java/org/apache/geode/test/dunit/rules/DistributedReference.java
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.geode.test.dunit.rules;
+
+import static org.apache.geode.test.dunit.VM.DEFAULT_VM_COUNT;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * JUnit Rule that provides a static reference in every distributed test
{@code VM}s including the
+ * main JUnit controller {@code VM}. If the referenced value is an {@code
AutoCloseable} or
+ * {@code Closeable} then it will be auto-closed in every {@code VM} during
tear down.
+ *
+ * <p>
+ * If the referenced value is not an {@code AutoCloseable} or {@code
Closeable}, the
+ * {@code DistributedReference} will use reflection to invoke any method named
{@code close} or
+ * {@code disconnect} regardless of what interfaces are implemented.
+ *
+ * <p>
+ * If the referenced value is null in any {@code VM} then it will be ignored
in that {@code VM}
+ * during tear down.
+ *
+ * <p>
+ * In the following example, every {@code VM} has a {@code Cache} which will
be auto-closed during
+ * tear down:
+ *
+ * <pre>
+ * {@literal @}Rule
+ * public DistributedReference<Cache> cache = new
DistributedReference<>();
+ *
+ * {@literal @}Before
+ * public void setUp() {
+ * Properties configProperties = new Properties();
+ * configProperties.setProperty(LOCATORS,
DistributedTestUtils.getLocators());
+ *
+ * for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ * vm.invoke(() -> {
+ * cache.set(new CacheFactory(configProperties).create());
+ * });
+ * }
+ * }
+ *
+ * {@literal @}Test
+ * public void eachVmHasItsOwnCache() {
+ * for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ * vm.invoke(() -> {
+ * assertThat(cache.get()).isInstanceOf(Cache.class);
+ * });
+ * }
+ * }
+ * </pre>
+ *
+ * <p>
+ * In the following example, every {@code VM} has a {@code DistributedSystem}
which will be
+ * auto-disconnected during tear down:
+ *
+ * <pre>
+ * {@literal @}Rule
+ * public DistributedReference<DistributedSystem> system = new
DistributedReference<>();
+ *
+ * {@literal @}Before
+ * public void setUp() {
+ * Properties configProperties = new Properties();
+ * configProperties.setProperty(LOCATORS,
DistributedTestUtils.getLocators());
+ *
+ * for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ * vm.invoke(() -> {
+ * system.set(DistributedSystem.connect(configProperties));
+ * });
+ * }
+ * }
+ *
+ * {@literal @}Test
+ * public void eachVmHasItsOwnSystemConnection() {
+ * for (VM vm : toArray(getVM(0), getVM(1), getVM(2), getVM(3),
getController())) {
+ * vm.invoke(() -> {
+ * assertThat(system.get()).isInstanceOf(DistributedSystem.class);
+ * });
+ * }
+ * }
+ * </pre>
+ *
+ * <p>
+ * To disable autoClose in a test, specify {@code autoClose(false)}:
+ *
+ * <pre>
+ * {@literal @}Rule
+ * public DistributedReference<DistributedSystem> system =
+ * new DistributedReference<>().autoClose(false);
+ * </pre>
+ */
+@SuppressWarnings({"serial", "unused"})
+public class DistributedReference<V> extends AbstractDistributedRule {
+
+ private static final AtomicReference<Object> reference = new
AtomicReference<>();
+
+ private final AtomicBoolean autoClose = new AtomicBoolean(true);
+
+ public DistributedReference() {
+ this(DEFAULT_VM_COUNT);
+ }
+
+ public DistributedReference(int vmCount) {
+ super(vmCount);
+ }
+
+ /**
+ * Set false to disable autoClose during tearDown. Default is true.
+ */
+ public DistributedReference<V> autoClose(boolean value) {
+ autoClose.set(value);
+ return this;
+ }
+
+ /**
+ * Gets the current value.
+ *
+ * @return the current value
+ */
+ @SuppressWarnings("unchecked")
+ public V get() {
+ return (V) reference.get();
+ }
+
+ /**
+ * Sets to the given value.
+ *
+ * @param newValue the new value
+ */
+ public void set(V newValue) {
+ reference.set(newValue);
+ }
+
+ @Override
+ protected void after() {
+ invoker().invokeInEveryVMAndController(this::invokeAfter);
+ }
+
+ private void invokeAfter() {
+ V value = get();
+ if (value == null) {
+ return;
+ }
+ reference.set(null);
+
+ if (autoClose.get()) {
+ autoClose(value);
+ }
+ }
+
+ private void autoClose(V value) {
+ if (value instanceof AutoCloseable) {
+ close((AutoCloseable) value);
+
+ } else if (hasMethod(value.getClass(), "close")) {
+ invokeMethod(value, "close");
+
+ } else if (hasMethod(value.getClass(), "disconnect")) {
+ invokeMethod(value, "disconnect");
+
+ } else if (hasMethod(value.getClass(), "stop")) {
+ invokeMethod(value, "stop");
+ }
+ }
+
+ private static void close(AutoCloseable autoCloseable) {
+ try {
+ autoCloseable.close();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static boolean hasMethod(Class<?> objectClass, String methodName) {
+ try {
+ Method method = objectClass.getMethod(methodName);
+ Class<?> returnType = method.getReturnType();
+ // currently only supports public method with zero parameters
+ if (method.getParameterCount() == 0 &&
+ Modifier.isPublic(method.getModifiers())) {
+ return true;
+ }
+ } catch (NoSuchMethodException e) {
+ // ignore
+ }
+ return false;
+ }
+
+ private static void invokeMethod(Object object, String methodName) {
+ try {
+ Method method = object.getClass().getMethod(methodName);
+ method.invoke(object);
+ } catch (NoSuchMethodException | InvocationTargetException |
IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}