GEODE-8775: Add gfsh execute function support (#708)

* Add gfsh execute function support to the new C++ test framework.
diff --git a/cppcache/integration/framework/Gfsh.cpp b/cppcache/integration/framework/Gfsh.cpp
index 1001c15..17ad576 100644
--- a/cppcache/integration/framework/Gfsh.cpp
+++ b/cppcache/integration/framework/Gfsh.cpp
@@ -29,6 +29,8 @@
 
 Gfsh::Deploy Gfsh::deploy() { return Deploy(*this); }
 
+Gfsh::ExecuteFunction Gfsh::executeFunction() { return ExecuteFunction(*this); }
+
 Gfsh::Verb::Verb(Gfsh &gfsh) : gfsh_(gfsh) {}
 
 Gfsh::Start::Start(Gfsh &gfsh) : gfsh_(gfsh) {}
@@ -60,16 +62,17 @@
   return *this;
 }
 
-Gfsh::Start::Locator &Gfsh::Start::Locator::withRemoteLocators(const std::vector<uint16_t> &locatorPorts) {
+Gfsh::Start::Locator &Gfsh::Start::Locator::withRemoteLocators(
+    const std::vector<uint16_t> &locatorPorts) {
   // Example: --J='-Dgemfire.remote-locators=localhost[9009],localhost[9010]'
-  if ( !locatorPorts.empty() ) {
+  if (!locatorPorts.empty()) {
     command_ += " --J='-Dgemfire.remote-locators=";
-    bool firstLocator=true;
+    bool firstLocator = true;
     for (uint16_t locatorPort : locatorPorts) {
-      if (firstLocator){
+      if (firstLocator) {
         command_ += "localhost[" + std::to_string(locatorPort) + "]";
-        firstLocator=false;
-      }else{
+        firstLocator = false;
+      } else {
         command_ += ",localhost[" + std::to_string(locatorPort) + "]";
       }
     }
@@ -78,9 +81,10 @@
   return *this;
 }
 
-Gfsh::Start::Locator &Gfsh::Start::Locator::withDistributedSystemId(const uint16_t &dsId) {
-  if ( dsId != 0 ){
-    command_ += " --J=-Dgemfire.distributed-system-id="+std::to_string(dsId);
+Gfsh::Start::Locator &Gfsh::Start::Locator::withDistributedSystemId(
+    const uint16_t &dsId) {
+  if (dsId != 0) {
+    command_ += " --J=-Dgemfire.distributed-system-id=" + std::to_string(dsId);
   }
   return *this;
 }
@@ -395,38 +399,49 @@
   return *this;
 }
 
-Gfsh::Create::Region &Gfsh::Create::Region::withRedundantCopies(const std::string &copies) {
+Gfsh::Create::Region &Gfsh::Create::Region::withRedundantCopies(
+    const std::string &copies) {
   command_ += " --redundant-copies=" + copies;
   return *this;
 }
 
-Gfsh::Create::Region &Gfsh::Create::Region::withBuckets(const std::string &totalNumBuckets) {
+Gfsh::Create::Region &Gfsh::Create::Region::withBuckets(
+    const std::string &totalNumBuckets) {
   command_ += " --total-num-buckets=" + totalNumBuckets;
   return *this;
 }
 
-Gfsh::Create::Region &Gfsh::Create::Region::withGatewaySenderId(const std::string &gatewaySenderId) {
+Gfsh::Create::Region &Gfsh::Create::Region::withGatewaySenderId(
+    const std::string &gatewaySenderId) {
   command_ += " --gateway-sender-id=" + gatewaySenderId;
   return *this;
 }
 
-Gfsh::Create::GatewaySender Gfsh::Create::gatewaySender() { return GatewaySender{gfsh_}; }
+Gfsh::Create::GatewaySender Gfsh::Create::gatewaySender() {
+  return GatewaySender{gfsh_};
+}
 
-Gfsh::Create::GatewaySender::GatewaySender(Gfsh &gfsh) : Command(gfsh, "create gateway-sender") {}
+Gfsh::Create::GatewaySender::GatewaySender(Gfsh &gfsh)
+    : Command(gfsh, "create gateway-sender") {}
 
-Gfsh::Create::GatewaySender &Gfsh::Create::GatewaySender::withId(const std::string &id){
+Gfsh::Create::GatewaySender &Gfsh::Create::GatewaySender::withId(
+    const std::string &id) {
   command_ += " --id=" + id;
   return *this;
 }
 
-Gfsh::Create::GatewaySender &Gfsh::Create::GatewaySender::withRemoteDSId(const std::string &remoteDSId){
+Gfsh::Create::GatewaySender &Gfsh::Create::GatewaySender::withRemoteDSId(
+    const std::string &remoteDSId) {
   command_ += " --remote-distributed-system-id=" + remoteDSId;
   return *this;
 }
 
-Gfsh::Create::GatewayReceiver Gfsh::Create::gatewayReceiver() { return GatewayReceiver{gfsh_}; }
+Gfsh::Create::GatewayReceiver Gfsh::Create::gatewayReceiver() {
+  return GatewayReceiver{gfsh_};
+}
 
-Gfsh::Create::GatewayReceiver::GatewayReceiver(Gfsh &gfsh) : Command(gfsh, "create gateway-receiver") {}
+Gfsh::Create::GatewayReceiver::GatewayReceiver(Gfsh &gfsh)
+    : Command(gfsh, "create gateway-receiver") {}
 
 Gfsh::Connect::Connect(Gfsh &gfsh) : Command{gfsh, "connect"} {}
 
@@ -509,3 +524,20 @@
 void Gfsh::Command<void>::execute() {
   gfsh_.execute(command_, "", "", "", "", "", "");
 }
+
+Gfsh::ExecuteFunction::ExecuteFunction(Gfsh &gfsh)
+    : Command{gfsh, "execute function"} {}
+
+Gfsh::ExecuteFunction &Gfsh::ExecuteFunction::withId(
+    const std::string &functionId) {
+  command_ += " --id=" + functionId;
+
+  return *this;
+}
+
+Gfsh::ExecuteFunction &Gfsh::ExecuteFunction::withMember(
+    const std::string &memberName) {
+  command_ += " --member=" + memberName;
+
+  return *this;
+}
diff --git a/cppcache/integration/framework/Gfsh.h b/cppcache/integration/framework/Gfsh.h
index 9154a5a..1170fe6 100644
--- a/cppcache/integration/framework/Gfsh.h
+++ b/cppcache/integration/framework/Gfsh.h
@@ -46,6 +46,9 @@
   class Deploy;
   Deploy deploy();
 
+  class ExecuteFunction;
+  ExecuteFunction executeFunction();
+
   class Verb {
    public:
    protected:
@@ -56,11 +59,14 @@
   template <class Result>
   class Command {
    public:
-    virtual Result execute(const std::string &user, const std::string &password, const std::string &keyStorePath,
-                           const std::string &trustStorePath, const std::string &keyStorePassword,
+    virtual Result execute(const std::string &user, const std::string &password,
+                           const std::string &keyStorePath,
+                           const std::string &trustStorePath,
+                           const std::string &keyStorePassword,
                            const std::string &trustStorePassword) {
-      Result{gfsh_}.parse(gfsh_.execute(command_, user, password, keyStorePath, trustStorePath,
-              keyStorePassword, trustStorePassword));
+      Result{gfsh_}.parse(gfsh_.execute(command_, user, password, keyStorePath,
+                                        trustStorePath, keyStorePassword,
+                                        trustStorePassword));
     }
     virtual Result execute() {
       Result{gfsh_}.parse(gfsh_.execute(command_, "", "", "", "", "", ""));
@@ -302,17 +308,30 @@
     Deploy &jar(const std::string &jarFile);
   };
 
+  class ExecuteFunction : public Command<void> {
+   public:
+    explicit ExecuteFunction(Gfsh &gfsh);
+
+    ExecuteFunction &withId(const std::string &functionName);
+    ExecuteFunction &withMember(const std::string &withMember);
+  };
+
  protected:
   virtual void execute(const std::string &command, const std::string &user,
-                       const std::string &password, const std::string &keyStorePath,
-                       const std::string &trustStorePath, const std::string &keyStorePassword,
+                       const std::string &password,
+                       const std::string &keyStorePath,
+                       const std::string &trustStorePath,
+                       const std::string &keyStorePassword,
                        const std::string &trustStorePassword) = 0;
 };
 
 template <>
-void Gfsh::Command<void>::execute(const std::string &user, const std::string &password,
-                                  const std::string &keyStorePath, const std::string &trustStorePath,
-                                  const std::string &keyStorePassword, const std::string &trustStorePassword);
+void Gfsh::Command<void>::execute(const std::string &user,
+                                  const std::string &password,
+                                  const std::string &keyStorePath,
+                                  const std::string &trustStorePath,
+                                  const std::string &keyStorePassword,
+                                  const std::string &trustStorePassword);
 
 template <>
 void Gfsh::Command<void>::execute();