@Test
  public void testFunctionExecutionRejection() throws Exception {
    final Host host = Host.getHost(0);
    final VM server1 = host.getVM(0);
    final VM server2 = host.getVM(1);
    final VM client = host.getVM(2);
    final String regionName = "FuncRej";

    ServerPorts ports1 = startCacheServer(server1, 80f, 90f, regionName, false/* createPR */,
        false/* notifyBySubscription */, 0);
    ServerPorts ports2 = startCacheServer(server2, 80f, 90f, regionName, false/* createPR */,
        false/* notifyBySubscription */, 0);

    startClient(client, server1, ports1.getPort(), regionName);

    registerTestMemoryThresholdListener(server1);
    registerTestMemoryThresholdListener(server2);

    final RejectFunction function = new RejectFunction();
    final RejectFunction function2 = new RejectFunction("noRejFunc", false);
    Invoke.invokeInEveryVM(new SerializableCallable("register function") {
      @Override
      public Object call() throws Exception {
        FunctionService.registerFunction(function);
        FunctionService.registerFunction(function2);
        return null;
      }
    });

    client.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Pool p = PoolManager.find("pool1");
        assertTrue(p != null);
        FunctionService.onServers(p).execute(function);
        FunctionService.onServers(p).execute(function2);
        return null;
      }
    });

    final DistributedMember s1 = (DistributedMember) server1.invoke(getDistributedMember);

    server2.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        FunctionService.onMembers().execute(function);
        FunctionService.onMember(s1).execute(function);
        FunctionService.onMembers().execute(function2);
        FunctionService.onMember(s1).execute(function2);
        return null;
      }
    });

    setUsageAboveCriticalThreshold(server1);

    verifyListenerValue(server2, MemoryState.CRITICAL, 1, true);

    server1.invoke(addExpectedFunctionException);
    server2.invoke(addExpectedFunctionException);

    client.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Pool p = PoolManager.find("pool1");
        assertTrue(p != null);
        try {
          FunctionService.onServers(p).execute(function);
          fail("expected LowMemoryExcception was not thrown");
        } catch (ServerOperationException e) {
          if (!(e.getCause().getMessage().matches(".*low.*memory.*"))) {
            Assert.fail("unexpected exception", e);
          }
          // expected
        }
        FunctionService.onServers(p).execute(function2);
        return null;
      }
    });

    server2.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        try {
          FunctionService.onMembers().execute(function);
          fail("expected LowMemoryExcception was not thrown");
        } catch (LowMemoryException e) {
          // expected
        }
        try {
          FunctionService.onMember(s1).execute(function);
          fail("expected LowMemoryExcception was not thrown");
        } catch (LowMemoryException e) {
          // expected
        }
        FunctionService.onMembers().execute(function2);
        FunctionService.onMember(s1).execute(function2);
        return null;
      }
    });
    server1.invoke(removeExpectedFunctionException);
    server2.invoke(removeExpectedFunctionException);
  }
Make sure appropriate events are delivered when moving between states.
geode-core/src/distributedTest/java/org/apache/geode/cache/management/MemoryThresholdsDUnitTest.java