This is an automated email from the ASF dual-hosted git repository.

mcmellawatt pushed a commit to branch release/1.8.0
in repository https://gitbox.apache.org/repos/asf/geode.git

commit e54e33d19135af64177145d96799d9974812d45d
Author: Jason Huynh <huyn...@gmail.com>
AuthorDate: Tue Nov 13 15:16:48 2018 -0800

    GEODE-5884: Added new command and restored pre 1.8 region function behavior 
(#2829)
    
    * Due to the refactor that caused us to lose wrapping of exceptions,
      the fix to GEODE-5884 cannot be applied to GEODE 1.0-1.7 clients
    * Adding new command class will allow clients to identify which function 
class
      it is expecting to execute and what behavior to expect
---
 .../cache/tier/sockets/CommandInitializer.java     |   7 +-
 .../sockets/command/ExecuteRegionFunction66.java   |   7 +-
 .../command/ExecuteRegionFunctionGeode18.java      |  62 +++++++++
 .../command/ExecuteRegionFunction66Test.java       |  22 ++-
 ....java => ExecuteRegionFunctionGeode18Test.java} |  42 +++---
 .../RollingUpgradeNonHAFunction.java               | 150 +++++++++++++++++++++
 6 files changed, 250 insertions(+), 40 deletions(-)

diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/CommandInitializer.java
 
b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/CommandInitializer.java
index 70857c7..f0cdd55 100644
--- 
a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/CommandInitializer.java
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/CommandInitializer.java
@@ -43,6 +43,7 @@ import 
org.apache.geode.internal.cache.tier.sockets.command.ExecuteFunction70;
 import 
org.apache.geode.internal.cache.tier.sockets.command.ExecuteRegionFunction;
 import 
org.apache.geode.internal.cache.tier.sockets.command.ExecuteRegionFunction65;
 import 
org.apache.geode.internal.cache.tier.sockets.command.ExecuteRegionFunction66;
+import 
org.apache.geode.internal.cache.tier.sockets.command.ExecuteRegionFunctionGeode18;
 import 
org.apache.geode.internal.cache.tier.sockets.command.ExecuteRegionFunctionSingleHop;
 import 
org.apache.geode.internal.cache.tier.sockets.command.GatewayReceiverCommand;
 import org.apache.geode.internal.cache.tier.sockets.command.Get70;
@@ -329,8 +330,12 @@ public class CommandInitializer {
     ALL_COMMANDS.put(Version.GEODE_150, commands);
     ALL_COMMANDS.put(Version.GEODE_160, commands);
     ALL_COMMANDS.put(Version.GEODE_170, commands);
-    ALL_COMMANDS.put(Version.GEODE_180, commands);
 
+    Map<Integer, Command> geode18Commands = new HashMap<Integer, Command>();
+    geode18Commands.putAll(ALL_COMMANDS.get(Version.GEODE_170));
+    geode18Commands.put(MessageType.EXECUTE_REGION_FUNCTION,
+        ExecuteRegionFunctionGeode18.getCommand());
+    ALL_COMMANDS.put(Version.GEODE_180, geode18Commands);
   }
 
   public static Map<Integer, Command> getCommands(Version version) {
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66.java
 
b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66.java
index 166d470..d6c701f 100644
--- 
a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66.java
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66.java
@@ -60,7 +60,7 @@ public class ExecuteRegionFunction66 extends BaseCommand {
     return singleton;
   }
 
-  private ExecuteRegionFunction66() {}
+  ExecuteRegionFunction66() {}
 
   @Override
   public void cmdExecute(final Message clientMessage, final ServerConnection 
serverConnection,
@@ -396,7 +396,6 @@ public class ExecuteRegionFunction66 extends BaseCommand {
     if (function instanceof String) {
       switch (functionState) {
         case AbstractExecution.NO_HA_HASRESULT_NO_OPTIMIZEFORWRITE:
-          execution.setWaitOnExceptionFlag(true);
           execution.execute((String) function).getResult();
           break;
         case AbstractExecution.HA_HASRESULT_NO_OPTIMIZEFORWRITE:
@@ -406,14 +405,10 @@ public class ExecuteRegionFunction66 extends BaseCommand {
           execution.execute((String) function).getResult();
           break;
         case AbstractExecution.NO_HA_HASRESULT_OPTIMIZEFORWRITE:
-          execution.setWaitOnExceptionFlag(true);
           execution.execute((String) function).getResult();
           break;
       }
     } else {
-      if (!functionObject.isHA()) {
-        execution.setWaitOnExceptionFlag(true);
-      }
       execution.execute(functionObject).getResult();
     }
   }
diff --git 
a/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunctionGeode18.java
 
b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunctionGeode18.java
new file mode 100644
index 0000000..386cd55
--- /dev/null
+++ 
b/geode-core/src/main/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunctionGeode18.java
@@ -0,0 +1,62 @@
+/*
+ * 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.tier.sockets.command;
+
+
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.internal.cache.execute.AbstractExecution;
+import org.apache.geode.internal.cache.tier.Command;
+
+/**
+ * @since Geode 1.8
+ */
+public class ExecuteRegionFunctionGeode18 extends ExecuteRegionFunction66 {
+
+  private static final ExecuteRegionFunctionGeode18 singleton = new 
ExecuteRegionFunctionGeode18();
+
+  public static Command getCommand() {
+    return singleton;
+  }
+
+  private ExecuteRegionFunctionGeode18() {}
+
+  void executeFunctionWithResult(Object function, byte functionState,
+      Function<?> functionObject, AbstractExecution execution) {
+    if (function instanceof String) {
+      switch (functionState) {
+        case AbstractExecution.NO_HA_HASRESULT_NO_OPTIMIZEFORWRITE:
+          execution.setWaitOnExceptionFlag(true);
+          execution.execute((String) function).getResult();
+          break;
+        case AbstractExecution.HA_HASRESULT_NO_OPTIMIZEFORWRITE:
+          execution.execute((String) function).getResult();
+          break;
+        case AbstractExecution.HA_HASRESULT_OPTIMIZEFORWRITE:
+          execution.execute((String) function).getResult();
+          break;
+        case AbstractExecution.NO_HA_HASRESULT_OPTIMIZEFORWRITE:
+          execution.setWaitOnExceptionFlag(true);
+          execution.execute((String) function).getResult();
+          break;
+      }
+    } else {
+      if (!functionObject.isHA()) {
+        execution.setWaitOnExceptionFlag(true);
+      }
+      execution.execute(functionObject).getResult();
+    }
+  }
+
+}
diff --git 
a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66Test.java
 
b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66Test.java
index f7d369e..24be2e9 100644
--- 
a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66Test.java
+++ 
b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66Test.java
@@ -67,37 +67,36 @@ public class ExecuteRegionFunction66Test {
   }
 
   @Test
-  public void executingFunctionByStringWithNoHAShouldSetWaitOnException() 
throws Exception {
+  public void 
executingFunctionInPreGeode18ByStringWithNoHAShouldNotSetWaitOnException() {
     AbstractExecution execution = mock(AbstractExecution.class);
     String functionName = "functionName";
     
when(execution.execute(functionName)).thenReturn(mock(ResultCollector.class));
     this.executeRegionFunction66.executeFunctionWithResult(functionName,
         AbstractExecution.NO_HA_HASRESULT_NO_OPTIMIZEFORWRITE, functionObject, 
execution);
-    verify(execution, times(1)).setWaitOnExceptionFlag(true);
+    verify(execution, times(0)).setWaitOnExceptionFlag(true);
   }
 
   @Test
-  public void 
executingFunctionByStringWithNoHAWithOptimizeForWriteShouldSetWaitOnException()
-      throws Exception {
+  public void 
executingFunctionInPreGeode18ByStringWithNoHAWithOptimizeForWriteShouldNotSetWaitOnException()
 {
     AbstractExecution execution = mock(AbstractExecution.class);
     String functionName = "functionName";
     
when(execution.execute(functionName)).thenReturn(mock(ResultCollector.class));
     this.executeRegionFunction66.executeFunctionWithResult(functionName,
         AbstractExecution.NO_HA_HASRESULT_OPTIMIZEFORWRITE, functionObject, 
execution);
-    verify(execution, times(1)).setWaitOnExceptionFlag(true);
+    verify(execution, times(0)).setWaitOnExceptionFlag(true);
   }
 
   @Test
-  public void executeFunctionObjectShouldSetWaitOnException() throws Exception 
{
+  public void executingFunctionObjectInPreGeode18ShouldNotSetWaitOnException() 
{
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
     this.executeRegionFunction66.executeFunctionWithResult(functionObject,
         AbstractExecution.NO_HA_HASRESULT_OPTIMIZEFORWRITE, functionObject, 
execution);
-    verify(execution, times(1)).setWaitOnExceptionFlag(true);
+    verify(execution, times(0)).setWaitOnExceptionFlag(true);
   }
 
   @Test
-  public void generateNullArgumentMessageIfRegionIsNull() throws Exception {
+  public void generateNullArgumentMessageIfRegionIsNull() {
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
     assertEquals("The input region for the execute function request is null",
@@ -105,7 +104,7 @@ public class ExecuteRegionFunction66Test {
   }
 
   @Test
-  public void generateNullArgumentMessageIfFunctionIsNullAndRegionIsNotNull() 
throws Exception {
+  public void generateNullArgumentMessageIfFunctionIsNullAndRegionIsNotNull() {
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
     assertEquals("The input function for the execute function request is null",
@@ -165,7 +164,7 @@ public class ExecuteRegionFunction66Test {
   }
 
   @Test
-  public void getAuthorizedExecuteFunctionReturnsNullIfAuthorizationIsNull() 
throws Exception {
+  public void getAuthorizedExecuteFunctionReturnsNullIfAuthorizationIsNull() {
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
     String functionName = "functionName";
@@ -177,8 +176,7 @@ public class ExecuteRegionFunction66Test {
   }
 
   @Test
-  public void 
getAuthorizedExecuteFunctionReturnsExecutionContextIfAuthorizeRequestIsNotNull()
-      throws Exception {
+  public void 
getAuthorizedExecuteFunctionReturnsExecutionContextIfAuthorizeRequestIsNotNull()
 {
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
     String functionName = "functionName";
diff --git 
a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66Test.java
 
b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunctionGeode18Test.java
similarity index 84%
copy from 
geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66Test.java
copy to 
geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunctionGeode18Test.java
index f7d369e..cbeb5d6 100644
--- 
a/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunction66Test.java
+++ 
b/geode-core/src/test/java/org/apache/geode/internal/cache/tier/sockets/command/ExecuteRegionFunctionGeode18Test.java
@@ -46,20 +46,21 @@ import org.apache.geode.internal.security.AuthorizeRequest;
 import org.apache.geode.test.junit.categories.ClientServerTest;
 
 @Category({ClientServerTest.class})
-public class ExecuteRegionFunction66Test {
+public class ExecuteRegionFunctionGeode18Test {
   private static final String FUNCTION_ID = "function_id";
 
   @Mock
   private Function functionObject;
 
-  private ExecuteRegionFunction66 executeRegionFunction66;
+  private ExecuteRegionFunctionGeode18 executeRegionFunctionGeode18;
 
   @Rule
   public RestoreSystemProperties restoreSystemProperties = new 
RestoreSystemProperties();
 
   @Before
   public void setUp() throws Exception {
-    this.executeRegionFunction66 = (ExecuteRegionFunction66) 
ExecuteRegionFunction66.getCommand();
+    this.executeRegionFunctionGeode18 =
+        (ExecuteRegionFunctionGeode18) 
ExecuteRegionFunctionGeode18.getCommand();
 
     this.functionObject = mock(Function.class);
     when(this.functionObject.getId()).thenReturn(FUNCTION_ID);
@@ -67,49 +68,48 @@ public class ExecuteRegionFunction66Test {
   }
 
   @Test
-  public void executingFunctionByStringWithNoHAShouldSetWaitOnException() 
throws Exception {
+  public void executingFunctionByStringWithNoHAShouldSetWaitOnException() {
     AbstractExecution execution = mock(AbstractExecution.class);
     String functionName = "functionName";
     
when(execution.execute(functionName)).thenReturn(mock(ResultCollector.class));
-    this.executeRegionFunction66.executeFunctionWithResult(functionName,
+    this.executeRegionFunctionGeode18.executeFunctionWithResult(functionName,
         AbstractExecution.NO_HA_HASRESULT_NO_OPTIMIZEFORWRITE, functionObject, 
execution);
     verify(execution, times(1)).setWaitOnExceptionFlag(true);
   }
 
   @Test
-  public void 
executingFunctionByStringWithNoHAWithOptimizeForWriteShouldSetWaitOnException()
-      throws Exception {
+  public void 
executingFunctionByStringWithNoHAWithOptimizeForWriteShouldSetWaitOnException() 
{
     AbstractExecution execution = mock(AbstractExecution.class);
     String functionName = "functionName";
     
when(execution.execute(functionName)).thenReturn(mock(ResultCollector.class));
-    this.executeRegionFunction66.executeFunctionWithResult(functionName,
+    this.executeRegionFunctionGeode18.executeFunctionWithResult(functionName,
         AbstractExecution.NO_HA_HASRESULT_OPTIMIZEFORWRITE, functionObject, 
execution);
     verify(execution, times(1)).setWaitOnExceptionFlag(true);
   }
 
   @Test
-  public void executeFunctionObjectShouldSetWaitOnException() throws Exception 
{
+  public void executeFunctionObjectShouldSetWaitOnException() {
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
-    this.executeRegionFunction66.executeFunctionWithResult(functionObject,
+    this.executeRegionFunctionGeode18.executeFunctionWithResult(functionObject,
         AbstractExecution.NO_HA_HASRESULT_OPTIMIZEFORWRITE, functionObject, 
execution);
     verify(execution, times(1)).setWaitOnExceptionFlag(true);
   }
 
   @Test
-  public void generateNullArgumentMessageIfRegionIsNull() throws Exception {
+  public void generateNullArgumentMessageIfRegionIsNull() {
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
     assertEquals("The input region for the execute function request is null",
-        this.executeRegionFunction66.generateNullArgumentMessage(null, null));
+        this.executeRegionFunctionGeode18.generateNullArgumentMessage(null, 
null));
   }
 
   @Test
-  public void generateNullArgumentMessageIfFunctionIsNullAndRegionIsNotNull() 
throws Exception {
+  public void generateNullArgumentMessageIfFunctionIsNullAndRegionIsNotNull() {
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
     assertEquals("The input function for the execute function request is null",
-        this.executeRegionFunction66.generateNullArgumentMessage("someRegion", 
null));
+        
this.executeRegionFunctionGeode18.generateNullArgumentMessage("someRegion", 
null));
   }
 
   @Test
@@ -132,7 +132,7 @@ public class ExecuteRegionFunction66Test {
     when(clientMessage.getPart(8)).thenReturn(part2);
     when(clientMessage.getPart(9)).thenReturn(part3);
     int filterSize = 3;
-    Set filter = this.executeRegionFunction66.populateFilters(clientMessage, 
filterSize);
+    Set filter = 
this.executeRegionFunctionGeode18.populateFilters(clientMessage, filterSize);
     assertSame(filterSize, filter.size());
     assertTrue(filter.contains(object1));
     assertTrue(filter.contains(object2));
@@ -158,27 +158,27 @@ public class ExecuteRegionFunction66Test {
     when(clientMessage.getPart(7)).thenReturn(part1);
     when(clientMessage.getPart(8)).thenReturn(part2);
     when(clientMessage.getPart(9)).thenReturn(part3);
-    Set nodes = 
this.executeRegionFunction66.populateRemovedNodes(clientMessage, 3, 6);
+    Set nodes = 
this.executeRegionFunctionGeode18.populateRemovedNodes(clientMessage, 3, 6);
     assertTrue(nodes.contains(object1));
     assertTrue(nodes.contains(object2));
     assertTrue(nodes.contains(object3));
   }
 
   @Test
-  public void getAuthorizedExecuteFunctionReturnsNullIfAuthorizationIsNull() 
throws Exception {
+  public void getAuthorizedExecuteFunctionReturnsNullIfAuthorizationIsNull() {
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
     String functionName = "functionName";
     String regionPath = "regionPath";
     ExecuteFunctionOperationContext context =
-        
executeRegionFunction66.getAuthorizedExecuteFunctionOperationContext(null, 
null, true, null,
+        
executeRegionFunctionGeode18.getAuthorizedExecuteFunctionOperationContext(null, 
null, true,
+            null,
             functionName, regionPath);
     assertNull(context);
   }
 
   @Test
-  public void 
getAuthorizedExecuteFunctionReturnsExecutionContextIfAuthorizeRequestIsNotNull()
-      throws Exception {
+  public void 
getAuthorizedExecuteFunctionReturnsExecutionContextIfAuthorizeRequestIsNotNull()
 {
     AbstractExecution execution = mock(AbstractExecution.class);
     
when(execution.execute(functionObject)).thenReturn(mock(ResultCollector.class));
     String functionName = "functionName";
@@ -188,7 +188,7 @@ public class ExecuteRegionFunction66Test {
         .thenReturn(mock(ExecuteFunctionOperationContext.class));
 
     ExecuteFunctionOperationContext context =
-        
executeRegionFunction66.getAuthorizedExecuteFunctionOperationContext(null, 
null, true,
+        
executeRegionFunctionGeode18.getAuthorizedExecuteFunctionOperationContext(null, 
null, true,
             request, functionName, regionPath);
     assertNotNull(context);
   }
diff --git 
a/geode-core/src/upgradeTest/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradeNonHAFunction.java
 
b/geode-core/src/upgradeTest/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradeNonHAFunction.java
new file mode 100644
index 0000000..2fc56a4
--- /dev/null
+++ 
b/geode-core/src/upgradeTest/java/org/apache/geode/internal/cache/rollingupgrade/RollingUpgradeNonHAFunction.java
@@ -0,0 +1,150 @@
+/*
+ * 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.awaitility.GeodeAwaitility.await;
+import static org.apache.geode.test.dunit.Assert.fail;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Properties;
+
+import org.junit.Test;
+
+import org.apache.geode.cache.GemFireCache;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.execute.Function;
+import org.apache.geode.cache.execute.FunctionContext;
+import org.apache.geode.cache.execute.FunctionInvocationTargetException;
+import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.cache.execute.ResultCollector;
+import org.apache.geode.cache30.CacheSerializableRunnable;
+import org.apache.geode.distributed.ConfigurationProperties;
+import org.apache.geode.distributed.internal.DistributionConfig;
+import org.apache.geode.distributed.internal.InternalLocator;
+import org.apache.geode.internal.AvailablePortHelper;
+import org.apache.geode.internal.Version;
+import org.apache.geode.test.dunit.Host;
+import org.apache.geode.test.dunit.NetworkUtils;
+import org.apache.geode.test.dunit.VM;
+import org.apache.geode.test.dunit.standalone.VersionManager;
+
+public class RollingUpgradeNonHAFunction extends RollingUpgrade2DUnitTestBase {
+
+  @Test
+  public void 
functionExceptionsThrownFromDifferentVersionServerShouldCorrectlyWrapFunctionExceptionCauses()
+      throws Exception {
+    final Host host = Host.getHost(0);
+    VM currentServer1 = host.getVM(VersionManager.CURRENT_VERSION, 0);
+    VM oldServer = host.getVM(oldVersion, 1);
+    VM currentServer2 = host.getVM(VersionManager.CURRENT_VERSION, 2);
+    VM oldServerAndLocator = host.getVM(oldVersion, 3);
+
+    String regionName = "cqs";
+
+    RegionShortcut shortcut = RegionShortcut.PARTITION;
+
+    String serverHostName = NetworkUtils.getServerHostName();
+    int port = AvailablePortHelper.getRandomAvailableTCPPort();
+    try {
+      Properties props = getSystemProperties();
+      props.put(ConfigurationProperties.SERIALIZABLE_OBJECT_FILTER,
+          "org.apache.geode.internal.cache.rollingupgrade.**");
+      props.remove(DistributionConfig.LOCATORS_NAME);
+      invokeRunnableInVMs(invokeStartLocatorAndServer(serverHostName, port, 
props),
+          oldServerAndLocator);
+
+      // Locators before 1.4 handled configuration asynchronously.
+      // We must wait for configuration configuration to be ready, or confirm 
that it is disabled.
+      oldServerAndLocator.invoke(
+          () -> await()
+              .untilAsserted(() -> assertTrue(
+                  
!InternalLocator.getLocator().getConfig().getEnableClusterConfiguration()
+                      || 
InternalLocator.getLocator().isSharedConfigurationRunning())));
+
+      props.put(DistributionConfig.LOCATORS_NAME, serverHostName + "[" + port 
+ "]");
+      invokeRunnableInVMs(invokeCreateCache(props), currentServer1, 
currentServer2, oldServer);
+
+      currentServer1.invoke(invokeAssertVersion(Version.CURRENT_ORDINAL));
+      currentServer2.invoke(invokeAssertVersion(Version.CURRENT_ORDINAL));
+
+      // create region
+      invokeRunnableInVMs(invokeCreateRegion(regionName, shortcut), 
currentServer1, currentServer2,
+          oldServer, oldServerAndLocator);
+
+      // Locators before 1.4 handled configuration asynchronously.
+      // We must wait for configuration configuration to be ready, or confirm 
that it is disabled.
+      oldServerAndLocator.invoke(
+          () -> await()
+              .untilAsserted(() -> assertTrue(
+                  
!InternalLocator.getLocator().getConfig().getEnableClusterConfiguration()
+                      || 
InternalLocator.getLocator().isSharedConfigurationRunning())));
+
+      putDataSerializableAndVerify(currentServer1, regionName, 0, 100, 
currentServer2, oldServer,
+          oldServerAndLocator);
+      runFunction("/" + regionName, currentServer1,
+          currentServer2, oldServer, oldServerAndLocator);
+
+    } finally {
+      invokeRunnableInVMs(invokeCloseCache(), currentServer1, currentServer2, 
oldServer,
+          oldServerAndLocator);
+    }
+  }
+
+  protected void runFunction(String queryString, VM... vms) {
+    for (VM vm : vms) {
+      vm.invoke(invokeAssertFunctionResults(queryString));
+    }
+  }
+
+  private CacheSerializableRunnable invokeAssertFunctionResults(final String 
queryString) {
+    return new CacheSerializableRunnable("execute: assertQueryResults") {
+      public void run2() {
+        try {
+          invokeAssertFunctionResult(RollingUpgrade2DUnitTestBase.cache, 
queryString);
+        } catch (Exception e) {
+          fail("Error asserting query results", e);
+        }
+      }
+    };
+  }
+
+  private static void invokeAssertFunctionResult(GemFireCache cache, String 
regionName) {
+    ResultCollector rc = null;
+    try {
+      rc = FunctionService.onRegion(cache.getRegion(regionName)).execute(new 
ExceptionalFunction());
+      rc.getResult();
+      fail("Function executed was expected to throw an exception");
+    } catch (Exception e) {
+      assertNotNull(e.getCause());
+      assertSame(FunctionInvocationTargetException.class, 
e.getCause().getClass());
+    }
+  }
+
+  private static class ExceptionalFunction implements Function {
+
+    @Override
+    public void execute(FunctionContext context) {
+      throw new FunctionInvocationTargetException("This is an explicitly 
thrown test exception");
+    }
+
+    @Override
+    public boolean isHA() {
+      return false;
+    }
+  }
+
+}

Reply via email to