@Test
  public void testFunctionCalls() throws CacheException {
    final Host host = Host.getHost(0);
    VM vm0 = host.getVM(0);
    VM vm1 = host.getVM(1);
    VM vm2 = host.getVM(2);
    VM vm3 = host.getVM(3);
    final int numberOfEntries = 10;
    final String[] queryStr =
        new String[] {"SELECT * FROM " + regName + " pf where pf.getIdValue() > 0", // 0
            "SELECT * FROM " + regName + " pf where pf.test.getId() > 0", // 1
            "SELECT * FROM " + regName + " pf, pf.positions.values pos where "
                + "pos.getSecId() != 'VMWARE'", // 2
            "SELECT * FROM " + regName + " pf, pf.positions.values pos where "
                + "pf.getIdValue() > 0 and pos.getSecId() != 'VMWARE'", // 3
            "SELECT * FROM " + regName + " pf, pf.getPositions('test').values pos where "
                + "pos.getSecId() != 'VMWARE'", // 4
            "SELECT * FROM " + regName + " pf, pf.getPositions('test').values pos where "
                + "pf.id > 0 and pos.getSecId() != 'IBM'", // 5
            "SELECT * FROM " + regName + " pf, pf.getPositions('test').values pos where "
                + "pf.getIdValue() > 0 and pos.secId != 'IBM'", // 6
        };

    final int numPositionsPerTestObject = 2;

    final int[] numberOfTestObjectForAllQueries = new int[] {numberOfEntries, // Query 0
        0, // Query 1
        0, // Query 2
        numberOfEntries, // Query 3
        numberOfEntries, // Query 4
        numberOfEntries, // Query 5
        numberOfEntries, // Query 6
    };

    final int[] numberOfTestObject2ForAllQueries = new int[] {numberOfEntries, // Query 0
        numberOfEntries, // Query 1
        0, // Query 2
        numberOfEntries, // Query 3
        numberOfEntries, // Query 4
        numberOfEntries, // Query 5
        numberOfEntries, // Query 6
    };

    final int[] numberOfPositionPdxForAllQueries =
        new int[] {(numberOfEntries * numPositionsPerTestObject), // Query 0
            0, // Query 1
            (numberOfEntries * numPositionsPerTestObject), // 2
            (numberOfEntries * numPositionsPerTestObject * 2), // 3
            (numberOfEntries * numPositionsPerTestObject), // 4
            (numberOfEntries * numPositionsPerTestObject), // 5
            (numberOfEntries * numPositionsPerTestObject), // 6
        };


    // Start server1
    vm0.invoke(new CacheSerializableRunnable("Create cache server") {
      @Override
      public void run2() throws CacheException {
        configAndStartBridgeServer();
        Region region = getRootRegion().getSubregion(regionName);
      }
    });

    // Start server2
    vm1.invoke(new CacheSerializableRunnable("Create cache server") {
      @Override
      public void run2() throws CacheException {
        configAndStartBridgeServer();
        Region region = getRootRegion().getSubregion(regionName);
      }
    });


    // Client pool.
    final int port0 = vm0.invoke(PdxQueryDUnitTest::getCacheServerPort);
    final int port1 = vm1.invoke(PdxQueryDUnitTest::getCacheServerPort);

    final String host0 = NetworkUtils.getServerHostName(vm0.getHost());

    // Create client pool.
    final String poolName = "testClientServerQueryPool";
    createPool(vm2, poolName, new String[] {host0}, new int[] {port0}, true);
    createPool(vm3, poolName, new String[] {host0}, new int[] {port1}, true);

    final int dupIndex = 2;

    // Create client region
    vm3.invoke(new CacheSerializableRunnable("Create region") {
      @Override
      public void run2() throws CacheException {

        AttributesFactory factory = new AttributesFactory();
        factory.setScope(Scope.LOCAL);
        ClientServerTestCase.configureConnectionPool(factory, host0, port1, -1, true, -1, -1, null);
        Region region = createRegion(regionName, rootRegionName, factory.create());
        int j = 0;
        for (int i = 0; i < numberOfEntries; i++) {
          // insert duplicate values.
          if (i % dupIndex == 0) {
            j++;
          }
          region.put("key-" + i, new TestObject(j, "vmware", numPositionsPerTestObject));
        }
      }
    });


    for (int i = 0; i < queryStr.length; i++) {
      final int testObjectCnt = numberOfTestObjectForAllQueries[i];
      final int positionObjectCnt = numberOfPositionPdxForAllQueries[i];
      final int testObjCnt = numberOfTestObject2ForAllQueries[i];

      executeClientQueries(vm3, poolName, queryStr[i]);
      // Check for TestObject instances on Server2.

      vm1.invoke(new CacheSerializableRunnable("validate") {
        @Override
        public void run2() throws CacheException {
          assertEquals(testObjectCnt, TestObject.numInstance.get());
          assertEquals(positionObjectCnt, PositionPdx.numInstance);
          assertEquals(testObjCnt, TestObject2.numInstance.get());

          // Reset the instances
          TestObject.numInstance.set(0);
          PositionPdx.numInstance = 0;
          TestObject2.numInstance.set(0);
        }
      });
    }

    closeClient(vm2);
    closeClient(vm3);
    closeClient(vm1);
    closeClient(vm0);
  }
Tests function calls in the query.
geode-core/src/distributedTest/java/org/apache/geode/cache/query/dunit/PdxQueryDUnitTest.java