@Test
  public void testP2PPartitionedRegionsFunctionExecutionStats() {
    final String rName = getUniqueName();
    Host host = Host.getHost(0);
    final VM datastore0 = host.getVM(0);
    final VM datastore1 = host.getVM(1);
    final VM datastore2 = host.getVM(2);
    final VM accessor = host.getVM(3);

    datastore0.invoke(initializeStats);
    datastore1.invoke(initializeStats);
    datastore2.invoke(initializeStats);
    accessor.invoke(initializeStats);

    accessor.invoke(() -> {
      RegionAttributes ra = PartitionedRegionTestHelper.createRegionAttrsForPR(0, 0);
      AttributesFactory raf = new AttributesFactory(ra);
      PartitionAttributesImpl pa = new PartitionAttributesImpl();
      pa.setAll(ra.getPartitionAttributes());
      pa.setTotalNumBuckets(17);
      raf.setPartitionAttributes(pa);

      getCache().createRegion(rName, raf.create());
    });

    SerializableRunnableIF dataStoreCreate = () -> {
      RegionAttributes ra = PartitionedRegionTestHelper.createRegionAttrsForPR(0, 10);
      AttributesFactory raf = new AttributesFactory(ra);
      PartitionAttributesImpl pa = new PartitionAttributesImpl();
      pa.setAll(ra.getPartitionAttributes());
      pa.setTotalNumBuckets(17);
      raf.setPartitionAttributes(pa);
      getCache().createRegion(rName, raf.create());
      Function function = new TestFunction(true, TestFunction.TEST_FUNCTION2);
      FunctionService.registerFunction(function);
      function = new TestFunction(true, TestFunction.TEST_FUNCTION3);
      FunctionService.registerFunction(function);
    };
    datastore0.invoke(dataStoreCreate);
    datastore1.invoke(dataStoreCreate);
    datastore2.invoke(dataStoreCreate);

    accessor.invoke(() -> {
      PartitionedRegion pr = (PartitionedRegion) getCache().getRegion(rName);
      DistributedSystem.setThreadsSocketPolicy(false);
      final HashSet<String> testKeys = new HashSet<>();
      for (int i = (pr.getTotalNumberOfBuckets() * 3); i > 0; i--) {
        testKeys.add("execKey-" + i);
      }
      int j = 0;
      for (Object testKey : testKeys) {
        Integer val = j++;
        pr.put(testKey, val);
      }
      Function function = new TestFunction(true, TestFunction.TEST_FUNCTION2);
      FunctionService.registerFunction(function);
      Execution dataSet = FunctionService.onRegion(pr);
      ResultCollector rc1 = dataSet.setArguments(Boolean.TRUE).execute(function);
      int size = ((List) rc1.getResult()).size();
      resultReceived_Aggregate += size;
      resultReceived_TESTFUNCTION2 += size;

      rc1 = dataSet.setArguments(testKeys).execute(function);
      size = ((List) rc1.getResult()).size();
      resultReceived_Aggregate += size;
      resultReceived_TESTFUNCTION2 += size;

      function = new TestFunction(true, TestFunction.TEST_FUNCTION3);
      FunctionService.registerFunction(function);
      rc1 = dataSet.setArguments(Boolean.TRUE).execute(function);
      size = ((List) rc1.getResult()).size();
      resultReceived_Aggregate += size;
      resultReceived_TESTFUNCTION3 += size;
    });

    accessor.invoke(() -> {
      InternalDistributedSystem iDS =
          ((InternalDistributedSystem) getCache().getDistributedSystem());
      FunctionServiceStats functionServiceStats =
          iDS.getFunctionStatsManager().getFunctionServiceStats();
      waitNoFunctionsRunning(functionServiceStats);

      assertEquals(noOfExecutionCalls_Aggregate,
          functionServiceStats.getFunctionExecutionCalls());
      assertEquals(noOfExecutionsCompleted_Aggregate,
          functionServiceStats.getFunctionExecutionsCompleted());
      assertEquals(resultReceived_Aggregate, functionServiceStats.getResultsReceived());

      FunctionStats functionStats =
          FunctionStatsManager.getFunctionStats(TestFunction.TEST_FUNCTION2, iDS);
      assertEquals(noOfExecutionCalls_TESTFUNCTION2, functionStats.getFunctionExecutionCalls());
      assertEquals(noOfExecutionsCompleted_TESTFUNCTION2,
          functionStats.getFunctionExecutionsCompleted());
      assertEquals(resultReceived_TESTFUNCTION2, functionStats.getResultsReceived());

      functionStats = FunctionStatsManager.getFunctionStats(TestFunction.TEST_FUNCTION3, iDS);
      assertEquals(noOfExecutionCalls_TESTFUNCTION3, functionStats.getFunctionExecutionCalls());
      assertEquals(noOfExecutionsCompleted_TESTFUNCTION3,
          functionStats.getFunctionExecutionsCompleted());
      assertEquals(resultReceived_TESTFUNCTION3, functionStats.getResultsReceived());
    });

    SerializableRunnableIF checkFunctionExecutionStatsForDataStore = () -> {
      InternalDistributedSystem iDS =
          ((InternalDistributedSystem) getCache().getDistributedSystem());
      // 3 Function Executions took place
      FunctionServiceStats functionServiceStats =
          iDS.getFunctionStatsManager().getFunctionServiceStats();
      waitNoFunctionsRunning(functionServiceStats);

      noOfExecutionCalls_Aggregate += 3;
      noOfExecutionsCompleted_Aggregate += 3;
      assertEquals(noOfExecutionCalls_Aggregate,
          functionServiceStats.getFunctionExecutionCalls());
      assertEquals(noOfExecutionsCompleted_Aggregate,
          functionServiceStats.getFunctionExecutionsCompleted());

      FunctionStats functionStats =
          FunctionStatsManager.getFunctionStats(TestFunction.TEST_FUNCTION2, iDS);
      // TEST_FUNCTION2 is executed twice
      noOfExecutionCalls_TESTFUNCTION2 += 2;
      assertEquals(noOfExecutionCalls_TESTFUNCTION2,
          functionStats.getFunctionExecutionCalls());
      noOfExecutionsCompleted_TESTFUNCTION2 += 2;
      assertEquals(noOfExecutionsCompleted_TESTFUNCTION2,
          functionStats.getFunctionExecutionsCompleted());

      functionStats = FunctionStatsManager.getFunctionStats(TestFunction.TEST_FUNCTION3, iDS);
      // TEST_FUNCTION3 is executed once
      noOfExecutionCalls_TESTFUNCTION3 += 1;
      assertEquals(noOfExecutionCalls_TESTFUNCTION3,
          functionStats.getFunctionExecutionCalls());
      noOfExecutionsCompleted_TESTFUNCTION3 += 1;
      assertEquals(noOfExecutionsCompleted_TESTFUNCTION3,
          functionStats.getFunctionExecutionsCompleted());
    };
    datastore0.invoke(checkFunctionExecutionStatsForDataStore);
    datastore1.invoke(checkFunctionExecutionStatsForDataStore);
    datastore2.invoke(checkFunctionExecutionStatsForDataStore);

    accessor.invoke(closeDistributedSystem);
    datastore0.invoke(closeDistributedSystem);
    datastore1.invoke(closeDistributedSystem);
    datastore2.invoke(closeDistributedSystem);
  }
Ensure that the execution is happening all the PR as a whole

Function Execution will not take place on accessor, accessor will onlu receive the
resultsReceived. On datastore, no of function execution calls should be equal to the no of
function execution calls from the accessor.
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/execute/FunctionServiceStatsDUnitTest.java