You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2020/10/14 18:22:37 UTC
[geode] 22/22: GEODE-7845: Adding a cleaner simpler test. (#5622)
This is an automated email from the ASF dual-hosted git repository.
jinmeiliao pushed a commit to branch feature/GEODE-7665
in repository https://gitbox.apache.org/repos/asf/geode.git
commit 30a699df1d5084de06e9a29a00bf89095f1de53b
Author: mhansonp <ha...@vmware.com>
AuthorDate: Tue Oct 13 17:09:03 2020 -0700
GEODE-7845: Adding a cleaner simpler test. (#5622)
- Changed the test for ServerVersionMismatchException to be more readable.
---
...ionRegionClearMixedServerPartitionedRegion.java | 412 ---------------------
...ePartitionRegionClearServerVersionMismatch.java | 174 +++++++++
2 files changed, 174 insertions(+), 412 deletions(-)
diff --git a/geode-core/src/upgradeTest/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradePartitionRegionClearMixedServerPartitionedRegion.java b/geode-core/src/upgradeTest/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradePartitionRegionClearMixedServerPartitionedRegion.java
deleted file mode 100644
index bfcd651..0000000
--- a/geode-core/src/upgradeTest/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradePartitionRegionClearMixedServerPartitionedRegion.java
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * 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.internal.cache.rollingupgrade;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.catchThrowable;
-
-import java.io.File;
-import java.lang.reflect.Constructor;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Properties;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.logging.log4j.Logger;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-import org.junit.runners.Parameterized.UseParametersRunnerFactory;
-
-import org.apache.geode.cache.Cache;
-import org.apache.geode.cache.CacheFactory;
-import org.apache.geode.cache.GemFireCache;
-import org.apache.geode.cache.Region;
-import org.apache.geode.cache.RegionFactory;
-import org.apache.geode.cache.RegionShortcut;
-import org.apache.geode.cache.ServerVersionMismatchException;
-import org.apache.geode.cache.client.ClientCache;
-import org.apache.geode.cache.client.ClientCacheFactory;
-import org.apache.geode.cache.client.ClientRegionShortcut;
-import org.apache.geode.cache.client.ServerOperationException;
-import org.apache.geode.cache.server.CacheServer;
-import org.apache.geode.distributed.DistributedSystem;
-import org.apache.geode.distributed.internal.DistributionConfig;
-import org.apache.geode.distributed.internal.membership.InternalDistributedMember;
-import org.apache.geode.internal.AvailablePortHelper;
-import org.apache.geode.internal.cache.GemFireCacheImpl;
-import org.apache.geode.internal.cache.PartitionedRegion;
-import org.apache.geode.logging.internal.log4j.api.LogService;
-import org.apache.geode.test.dunit.DistributedTestUtils;
-import org.apache.geode.test.dunit.Host;
-import org.apache.geode.test.dunit.IgnoredException;
-import org.apache.geode.test.dunit.Invoke;
-import org.apache.geode.test.dunit.NetworkUtils;
-import org.apache.geode.test.dunit.VM;
-import org.apache.geode.test.dunit.internal.DUnitLauncher;
-import org.apache.geode.test.dunit.internal.JUnit4DistributedTestCase;
-import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory;
-import org.apache.geode.test.version.VersionManager;
-
-@RunWith(Parameterized.class)
-@UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class)
-public class RollingUpgradePartitionRegionClearMixedServerPartitionedRegion
- extends JUnit4DistributedTestCase {
-
- protected static final Logger logger = LogService.getLogger();
- protected static GemFireCache cache;
- protected static ClientCache clientcache;
-
- @Parameter
- public String oldVersion;
-
- @Parameters(name = "from_v{0}")
- public static Collection<String> data() {
- List<String> result = VersionManager.getInstance().getVersionsWithoutCurrent();
- if (result.size() < 1) {
- throw new RuntimeException("No older versions of Geode were found to test against");
- } else {
- System.out.println("running against these versions: " + result);
- }
- return result;
- }
-
- @Test
- public void testPutAndGetMixedServerPartitionedRegion() throws Exception {
- doTestPutAndGetMixedServers(oldVersion);
- }
-
- /**
- * This test starts up multiple servers from the current code base and multiple servers from the
- * old version and executes puts and gets on a new server and old server and verifies that the
- * results are present. Note that the puts have overlapping region keys just to test new puts and
- * replaces
- */
- void doTestPutAndGetMixedServers(String oldVersion)
- throws Exception {
- VM currentServer1 = VM.getVM(VersionManager.CURRENT_VERSION, 0);
- VM oldServerAndLocator = VM.getVM(oldVersion, 1);
- VM currentServer2 = VM.getVM(VersionManager.CURRENT_VERSION, 2);
- VM oldServer2 = VM.getVM(oldVersion, 3);
-
- String regionName = "aRegion";
-
- final String serverHostName = NetworkUtils.getServerHostName();
- final int port = AvailablePortHelper.getRandomAvailableTCPPort();
- oldServerAndLocator.invoke(() -> DistributedTestUtils.deleteLocatorStateFile(port));
- try {
- final Properties props = getSystemProperties();
- props.remove(DistributionConfig.LOCATORS_NAME);
-
- // Fire up the locator and server
- oldServerAndLocator.invoke(() -> {
- props.put(DistributionConfig.START_LOCATOR_NAME,
- "" + serverHostName + "[" + port + "]");
- props.put(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "false");
- cache = createCache(props);
- Thread.sleep(5000); // bug in 1.0 - cluster config service not immediately available
- });
-
- props.put(DistributionConfig.LOCATORS_NAME, serverHostName + "[" + port + "]");
-
- // create the cache in all the server VMs.
- for (VM vm : Arrays.asList(oldServer2, currentServer1, currentServer2)) {
- vm.invoke(() -> {
- cache = createCache(props);
- });
- }
- // spin up current version servers
- for (VM vm : Arrays.asList(currentServer1, currentServer2)) {
- vm.invoke(
- () -> assertVersion(cache, VersionManager.getInstance().getCurrentVersionOrdinal()));
- }
-
- // create region
- for (VM vm : Arrays.asList(currentServer1, currentServer2, oldServerAndLocator, oldServer2)) {
- vm.invoke(() -> createRegion(cache, regionName));
- }
-
- // put some data in the region to make sure there is something to clear.
- putDataSerializableAndVerify(currentServer1, regionName, currentServer2, oldServerAndLocator,
- oldServer2);
-
- // invoke Partition Region Clear and verify we didn't touch the old servers.
-
- currentServer1.invoke(() -> {
- assertRegionExists(cache, regionName);
- PartitionedRegion region = (PartitionedRegion) cache.getRegion(regionName);
-
- Throwable thrown = catchThrowable(region::clear);
- assertThat(thrown).isInstanceOf(ServerVersionMismatchException.class);
-
- });
- } finally {
- for (VM vm : Arrays.asList(currentServer1, currentServer2, oldServerAndLocator, oldServer2)) {
- vm.invoke(
- () -> closeCache(RollingUpgradePartitionRegionClearMixedServerPartitionedRegion.cache));
- }
- }
- }
-
- @Test
- public void TestClientServerGetsUnsupportedExceptionWhenPRClearInvoked() throws Exception {
- doTestClientServerGetsUnsupportedExceptionWhenPRClearInvoked(oldVersion);
- }
-
- void doTestClientServerGetsUnsupportedExceptionWhenPRClearInvoked(String oldVersion)
- throws Exception {
-
- VM client = VM.getVM(VersionManager.CURRENT_VERSION, 0);
- VM locator = VM.getVM(VersionManager.CURRENT_VERSION, 1);
- VM currentServer = VM.getVM(VersionManager.CURRENT_VERSION, 2);
- VM oldServer2 = VM.getVM(oldVersion, 3);
-
- for (VM vm : Arrays.asList(locator, currentServer, client)) {
- vm.invoke(() -> System.setProperty("gemfire.allow_old_members_to_join_for_testing", "true"));
- }
-
- String regionName = "aRegion";
-
- final String serverHostName = NetworkUtils.getServerHostName();
- final int port = AvailablePortHelper.getRandomAvailableTCPPort();
- locator.invoke(() -> DistributedTestUtils.deleteLocatorStateFile(port));
- try {
- final Properties props = getSystemProperties();
- props.remove(DistributionConfig.LOCATORS_NAME);
-
- // Fire up the locator and server
- locator.invoke(() -> {
- props.put(DistributionConfig.START_LOCATOR_NAME,
- "" + serverHostName + "[" + port + "]");
- props.put(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "false");
- cache = createCache(props);
- });
-
- props.put(DistributionConfig.LOCATORS_NAME, serverHostName + "[" + port + "]");
-
- // create the cache in all the server VMs.
- for (VM vm : Arrays.asList(oldServer2, currentServer)) {
- vm.invoke(() -> {
- props.setProperty(DistributionConfig.NAME_NAME, "vm" + VM.getVMId());
- cache = createCache(props);
- });
- }
- int[] ports = AvailablePortHelper.getRandomAvailableTCPPorts(2);
-
- oldServer2.invoke(() -> startCacheServer(cache, ports[0]));
- currentServer.invoke(() -> startCacheServer(cache, ports[1]));
-
- // create region
- for (VM vm : Arrays.asList(currentServer, locator, oldServer2)) {
- vm.invoke(() -> createRegion(cache, regionName));
- }
-
- // put some data in the region to make sure there is something to clear.
- putDataSerializableAndVerify(currentServer, regionName, locator, oldServer2);
-
- // invoke Partition Region Clear from the client and verify the exception.
- client.invoke(() -> {
- clientcache = new ClientCacheFactory().addPoolServer(serverHostName, ports[1]).create();
- Region<Object, Object> clientRegion = clientcache.createClientRegionFactory(
- ClientRegionShortcut.PROXY).create(regionName);
-
- clientRegion.put("key", "value");
-
- Throwable thrown = catchThrowable(clientRegion::clear);
- assertThat(thrown).isInstanceOf(ServerOperationException.class);
- assertThat(thrown).hasCauseInstanceOf(ServerVersionMismatchException.class);
- ServerVersionMismatchException serverVersionMismatchException =
- (ServerVersionMismatchException) thrown.getCause();
- assertThat(serverVersionMismatchException.getMessage()).contains("vm3");
- });
-
- } finally {
-
- for (VM vm : Arrays.asList(currentServer, locator, oldServer2)) {
- vm.invoke(() -> closeCache(cache));
- }
-
- client.invoke(() -> {
- if (cache != null && !clientcache.isClosed()) {
- clientcache.close(false);
- }
- });
- }
- }
-
- private String getLocatorString(int locatorPort) {
- return getDUnitLocatorAddress() + "[" + locatorPort + "]";
- }
-
- public String getLocatorString(int[] locatorPorts) {
- StringBuilder locatorString = new StringBuilder();
- int numLocators = locatorPorts.length;
- for (int i = 0; i < numLocators; i++) {
- locatorString.append(getLocatorString(locatorPorts[i]));
- if (i + 1 < numLocators) {
- locatorString.append(",");
- }
- }
- return locatorString.toString();
- }
-
- private Cache createCache(Properties systemProperties) {
- systemProperties.setProperty(DistributionConfig.USE_CLUSTER_CONFIGURATION_NAME, "false");
- if (VersionManager.getInstance().getCurrentVersionOrdinal() < 75) {
- systemProperties.remove("validate-serializable-objects");
- systemProperties.remove("serializable-object-filter");
- }
- CacheFactory cf = new CacheFactory(systemProperties);
- return cf.create();
- }
-
- private void startCacheServer(GemFireCache cache, int port) throws Exception {
- CacheServer cacheServer = ((GemFireCacheImpl) cache).addCacheServer();
- cacheServer.setPort(port);
- cacheServer.start();
- }
-
- protected void assertRegionExists(GemFireCache cache, String regionName) {
- Region<Object, Object> region = cache.getRegion(regionName);
- if (region == null) {
- throw new Error("Region: " + regionName + " does not exist");
- }
- }
-
- private void assertEntryExists(GemFireCache cache, String regionName) {
- assertRegionExists(cache, regionName);
- Region<Object, Object> region = cache.getRegion(regionName);
- for (int i = 0; i < 10; i++) {
- String key = "" + i;
- Object regionValue = region.get(key);
- assertThat(regionValue).describedAs("Entry for key:" + key + " does not exist").isNotNull();
- }
- }
-
- public void put(GemFireCache cache, String regionName, Object key, Object value) {
- Region<Object, Object> region = cache.getRegion(regionName);
- System.out.println(regionName + ".put(" + key + "," + value + ")");
- Object result = region.put(key, value);
- System.out.println("returned " + result);
- }
-
- private void createRegion(GemFireCache cache, String regionName) {
- RegionFactory<Object, Object> rf = ((GemFireCacheImpl) cache).createRegionFactory(
- RegionShortcut.PARTITION);
- System.out.println("created region " + rf.create(regionName));
- }
-
- void assertVersion(GemFireCache cache, short ordinal) {
- DistributedSystem system = cache.getDistributedSystem();
- int thisOrdinal =
- ((InternalDistributedMember) system.getDistributedMember()).getVersion()
- .ordinal();
- if (ordinal != thisOrdinal) {
- throw new Error(
- "Version ordinal:" + thisOrdinal + " was not the expected ordinal of:" + ordinal);
- }
- }
-
- private void closeCache(GemFireCache cache) {
- if (cache == null) {
- return;
- }
- boolean cacheClosed = cache.isClosed();
- if (!cacheClosed) {
- List<CacheServer> servers = ((Cache) cache).getCacheServers();
- for (CacheServer server : servers) {
- server.stop();
- }
- cache.close();
- }
- }
-
- /**
- * Get the port that the standard dunit locator is listening on.
- *
- */
- private String getDUnitLocatorAddress() {
- return Host.getHost(0).getHostName();
- }
-
- private void deleteVMFiles() {
- System.out.println("deleting files in vm" + VM.getVMId());
- File pwd = new File(".");
- for (File entry : pwd.listFiles()) {
- try {
- if (entry.isDirectory()) {
- FileUtils.deleteDirectory(entry);
- } else {
- if (!entry.delete()) {
- System.out.println("Could not delete " + entry);
- }
- }
- } catch (Exception e) {
- System.out.println("Could not delete " + entry + ": " + e.getMessage());
- }
- }
- }
-
- @Override
- public void postSetUp() {
- Invoke.invokeInEveryVM("delete files", this::deleteVMFiles);
- IgnoredException.addIgnoredException(
- "cluster configuration service not available|ConflictingPersistentDataException");
- }
-
-
- void putDataSerializableAndVerify(VM putter, String regionName,
- VM... vms) throws Exception {
- for (int i = 0; i < 10; i++) {
- Class aClass = Thread.currentThread().getContextClassLoader()
- .loadClass("org.apache.geode.cache.ExpirationAttributes");
- Constructor constructor = aClass.getConstructor(int.class);
- Object testDataSerializable = constructor.newInstance(i);
- int finalI = i;
- putter.invoke(() -> put(cache, regionName, "" + finalI, testDataSerializable));
- }
-
- // verify present in others
- for (VM vm : vms) {
- vm.invoke(() -> assertEntryExists(cache, regionName));
- }
- }
-
- public Properties getSystemProperties() {
- Properties props = DistributedTestUtils.getAllDistributedSystemProperties(new Properties());
- props.remove("disable-auto-reconnect");
- props.put(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "true");
- props.put(DistributionConfig.USE_CLUSTER_CONFIGURATION_NAME, "false");
- props.remove(DistributionConfig.LOAD_CLUSTER_CONFIG_FROM_DIR_NAME);
- props.remove(DistributionConfig.OFF_HEAP_MEMORY_SIZE_NAME);
- props.remove(DistributionConfig.LOCK_MEMORY_NAME);
- return props;
- }
-
- public Properties getSystemProperties(int[] locatorPorts) {
- Properties props = new Properties();
- String locatorString = getLocatorString(locatorPorts);
- props.setProperty("locators", locatorString);
- props.setProperty("mcast-port", "0");
- props.put(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "true");
- props.put(DistributionConfig.USE_CLUSTER_CONFIGURATION_NAME, "false");
- props.remove(DistributionConfig.LOAD_CLUSTER_CONFIG_FROM_DIR_NAME);
- props.setProperty(DistributionConfig.LOG_LEVEL_NAME, DUnitLauncher.logLevel);
- return props;
- }
-}
diff --git a/geode-core/src/upgradeTest/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradePartitionRegionClearServerVersionMismatch.java b/geode-core/src/upgradeTest/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradePartitionRegionClearServerVersionMismatch.java
new file mode 100644
index 0000000..144ea38
--- /dev/null
+++ b/geode-core/src/upgradeTest/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradePartitionRegionClearServerVersionMismatch.java
@@ -0,0 +1,174 @@
+/*
+ * 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.internal.cache.rollingupgrade;
+
+import static org.apache.geode.test.dunit.rules.ClusterStartupRule.getCache;
+import static org.apache.geode.test.dunit.rules.ClusterStartupRule.getClientCache;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.assertj.core.api.Assertions.catchThrowable;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.ServerVersionMismatchException;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientRegionFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.cache.client.ServerOperationException;
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.test.dunit.IgnoredException;
+import org.apache.geode.test.dunit.rules.ClientVM;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory;
+import org.apache.geode.test.version.VersionManager;
+
+/**
+ * This test class exists to test the ServerVersionMismatchException
+ * A ServerVersionMismatchException is thrown when a cluster has a server that is previous to
+ * version 1.14.0 which doesn't support the Partitioned Region Clear feature.
+ *
+ * When the exception is thrown it is expected to contain the members that have the bad version,
+ * the version number necessary, and the feature that is not supported.
+ */
+
+
+@RunWith(Parameterized.class)
+@Parameterized.UseParametersRunnerFactory(CategoryWithParameterizedRunnerFactory.class)
+public class RollingUpgradePartitionRegionClearServerVersionMismatch {
+
+ @Rule
+ public ClusterStartupRule cluster = new ClusterStartupRule();
+
+ @Parameterized.Parameter
+ public String oldVersion;
+
+ @Parameterized.Parameters(name = "from_v{0}")
+ public static Collection<String> data() {
+ List<String> result = VersionManager.getInstance().getVersionsWithoutCurrent();
+ if (result.size() < 1) {
+ throw new RuntimeException("No older versions of Geode were found to test against");
+ } else {
+ System.out.println("running against these versions: " + result);
+ }
+ return result;
+ }
+
+ // This is the message that we are expected to be in the exception in both tests below.
+ private static final String expectedMessage =
+ "A server's [server-2] version was too old (< GEODE 1.14.0) for : Partitioned Region Clear";
+
+ private MemberVM locator;
+ private MemberVM serverNew;
+
+ @Before
+ public void before() {
+ locator = cluster.startLocatorVM(0,
+ l -> l.withSystemProperty("gemfire.allow_old_members_to_join_for_testing", "true")
+ .withProperty(DistributionConfig.ENABLE_CLUSTER_CONFIGURATION_NAME, "false"));
+ final int locatorPort = locator.getPort();
+
+ serverNew = cluster.startServerVM(1, locatorPort);
+ MemberVM serverOld =
+ cluster.startServerVM(2, oldVersion, s -> s.withConnectionToLocator(locatorPort));
+
+ MemberVM.invokeInEveryMember(() -> {
+ Cache cache = getCache();
+ assertThat(cache).isNotNull();
+ getCache().createRegionFactory(RegionShortcut.PARTITION).create("regionA");
+ }, serverNew, serverOld);
+
+ // Put in some boiler plate data for region clear
+ serverNew.invoke(() -> {
+ Cache cache = getCache();
+ assertThat(cache).isNotNull();
+
+ Region<String, String> region = cache.getRegion("regionA");
+ region.put("A", "ValueA");
+ region.put("B", "ValueB");
+ });
+
+ }
+
+ /**
+ * testClient_ServerVersionMismatchException - validates that when a client invokes a partitioned
+ * region clear on a cluster where one server is running an unsupported version for this feature
+ * we return a ServerVersionMismatchException
+ */
+ @Test
+ public void testClient_ServerVersionMismatchException() throws Exception {
+ IgnoredException.addIgnoredException(ServerOperationException.class);
+ final int locatorPort = locator.getPort();
+ // Get a client VM
+ ClientVM clientVM = cluster.startClientVM(3, c -> c.withLocatorConnection(locatorPort));
+
+ clientVM.invoke(() -> {
+ // Validate we have a cache and region
+ ClientCache clientCache = getClientCache();
+ assertThat(clientCache).isNotNull();
+
+ ClientRegionFactory<String, String> clientRegionFactory =
+ clientCache.createClientRegionFactory(ClientRegionShortcut.PROXY);
+ Region<String, String> region = clientRegionFactory.create("regionA");
+ assertThat(region).isNotNull();
+
+ // Validate that we get a ServerVersionMismatchException wrapped in a ServerOperationException
+ Throwable thrown = catchThrowable(region::clear);
+ assertThat(thrown).isInstanceOf(ServerOperationException.class);
+ assertThat(thrown).hasCauseInstanceOf(ServerVersionMismatchException.class);
+
+ // Validate that the message is exactly as we expect it.
+ ServerVersionMismatchException serverVersionMismatchException =
+ (ServerVersionMismatchException) thrown.getCause();
+ assertThat(serverVersionMismatchException.getMessage()).isEqualTo(expectedMessage);
+ });
+ }
+
+ /**
+ * testServer_ServerVersionMismatchException - validates that when a partitioned region clear is
+ * invoked on a cluster where one server is running an unsupported version for this feature we
+ * return a ServerVersionMismatchException
+ */
+ @Test
+ public void testServer_ServerVersionMismatchException() {
+ IgnoredException.addIgnoredException(ServerOperationException.class);
+
+ serverNew.invoke(() -> {
+ // Validate we have a cache and region
+ Cache cache = getCache();
+ assertThat(cache).isNotNull();
+
+ Region<String, String> region = cache.getRegion("regionA");
+ assertThat(region).isNotNull();
+
+ // Validate that the message is exactly as we expect it.
+ assertThatThrownBy(region::clear).isInstanceOf(ServerVersionMismatchException.class)
+ .hasMessage(expectedMessage);
+
+ assertThat(region.get("A")).isEqualTo("ValueA");
+ assertThat(region.get("B")).isEqualTo("ValueB");
+ });
+ }
+}