http://git-wip-us.apache.org/repos/asf/incubator-geode/blob/a64f7f60/geode-core/src/test/java/org/apache/geode/cache/query/dunit/PdxQueryDUnitTest.java
----------------------------------------------------------------------
diff --git 
a/geode-core/src/test/java/org/apache/geode/cache/query/dunit/PdxQueryDUnitTest.java
 
b/geode-core/src/test/java/org/apache/geode/cache/query/dunit/PdxQueryDUnitTest.java
new file mode 100644
index 0000000..6f5e2c4
--- /dev/null
+++ 
b/geode-core/src/test/java/org/apache/geode/cache/query/dunit/PdxQueryDUnitTest.java
@@ -0,0 +1,3590 @@
+/*
+ * 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.cache.query.dunit;
+
+import static org.apache.geode.internal.Assert.fail;
+import static org.junit.Assert.assertEquals;
+
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.apache.geode.test.junit.categories.DistributedTest;
+import org.apache.logging.log4j.Logger;
+import org.junit.Test;
+
+import org.apache.geode.cache.AttributesFactory;
+import org.apache.geode.cache.Cache;
+import org.apache.geode.cache.CacheException;
+import org.apache.geode.cache.CacheFactory;
+import org.apache.geode.cache.PartitionAttributesFactory;
+import org.apache.geode.cache.Region;
+import org.apache.geode.cache.RegionShortcut;
+import org.apache.geode.cache.Scope;
+import org.apache.geode.cache.client.ClientCache;
+import org.apache.geode.cache.client.ClientCacheFactory;
+import org.apache.geode.cache.client.ClientRegionShortcut;
+import org.apache.geode.cache.client.PoolManager;
+import org.apache.geode.cache.query.CacheUtils;
+import org.apache.geode.cache.query.IndexType;
+import org.apache.geode.cache.query.Query;
+import org.apache.geode.cache.query.QueryService;
+import org.apache.geode.cache.query.SelectResults;
+import org.apache.geode.cache.query.Struct;
+import org.apache.geode.cache.query.data.PortfolioPdx;
+import org.apache.geode.cache.query.data.PositionPdx;
+import org.apache.geode.cache.query.internal.Undefined;
+import org.apache.geode.cache.server.CacheServer;
+import org.apache.geode.cache30.CacheSerializableRunnable;
+import org.apache.geode.cache30.ClientServerTestCase;
+import org.apache.geode.internal.AvailablePortHelper;
+import org.apache.geode.internal.cache.GemFireCacheImpl;
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.pdx.FieldType;
+import org.apache.geode.pdx.JSONFormatter;
+import org.apache.geode.pdx.PdxInstance;
+import org.apache.geode.pdx.PdxInstanceFactory;
+import org.apache.geode.pdx.internal.ClientTypeRegistration;
+import org.apache.geode.pdx.internal.PdxInstanceFactoryImpl;
+import org.apache.geode.pdx.internal.PdxType;
+import org.apache.geode.pdx.internal.PeerTypeRegistration;
+import org.apache.geode.pdx.internal.TypeRegistration;
+import org.apache.geode.test.dunit.Assert;
+import org.apache.geode.test.dunit.DistributedTestCase;
+import org.apache.geode.test.dunit.DistributedTestUtils;
+import org.apache.geode.test.dunit.Host;
+import org.apache.geode.test.dunit.Invoke;
+import org.apache.geode.test.dunit.NetworkUtils;
+import org.apache.geode.test.dunit.SerializableCallable;
+import org.apache.geode.test.dunit.SerializableRunnable;
+import org.apache.geode.test.dunit.VM;
+import org.junit.experimental.categories.Category;
+
+@Category(DistributedTest.class)
+public class PdxQueryDUnitTest extends PDXQueryTestBase {
+  public static final Logger logger = LogService.getLogger();
+
+  public PdxQueryDUnitTest() {
+    super();
+  }
+
+  /**
+   * Tests client-server query on PdxInstance. The client receives projected 
value.
+   */
+  @Test
+  public void testServerQuery() throws CacheException {
+
+    final Host host = Host.getHost(0);
+    VM vm0 = host.getVM(0);
+    VM vm1 = host.getVM(1);
+    final int numberOfEntries = 5;
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+      }
+    });
+
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        assertEquals(0, TestObject.numInstance);
+
+        // Execute query with different type of Results.
+        QueryService qs = getCache().getQueryService();
+        Query query = null;
+        SelectResults sr = null;
+        for (int i = 0; i < queryString.length; i++) {
+          try {
+            query = qs.newQuery(queryString[i]);
+            sr = (SelectResults) query.execute();
+          } catch (Exception ex) {
+            fail("Failed to execute query, " + ex.getMessage());
+          }
+
+          for (Object o : sr.asSet()) {
+            if (i == 0 && !(o instanceof Integer)) {
+              fail("Expected type Integer, not found in result set. Found type 
:" + o.getClass());
+            } else if (i == 1 && !(o instanceof TestObject)) {
+              fail(
+                  "Expected type TestObject, not found in result set. Found 
type :" + o.getClass());
+            } else if (i == 2 && !(o instanceof String)) {
+              fail("Expected type String, not found in result set. Found type 
:" + o.getClass());
+            }
+          }
+        }
+        // Pdx objects for local queries now get deserialized when results are 
iterated.
+        // So the deserialized objects are no longer cached in 
VMCachedDeserializable.
+        assertEquals(numberOfEntries * 2, TestObject.numInstance);
+      }
+    });
+
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+
+  /**
+   * Tests client-server query on PdxInstance. The client receives projected 
value.
+   */
+  @Test
+  public void testClientServerQueryWithProjections() 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;
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        class PdxObject extends TestObject {
+          PdxObject() {}
+
+          PdxObject(int id, String ticker) {
+            super(id, ticker);
+          }
+        };
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new PdxObject(i, "vmware"));
+        }
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        System.out.println("##### Region size is: " + region.size());
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    // Create client region
+    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 = "testClientServerQueriesWithParamsPool";
+    createPool(vm2, poolName, new String[] {host0}, new int[] {port0}, true);
+    createPool(vm3, poolName, new String[] {host0}, new int[] {port1}, true);
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        SelectResults results = null;
+        QueryService qService = null;
+        try {
+          qService = (PoolManager.find(poolName)).getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+        try {
+          logger.info("### Executing Query :" + queryString[0]);
+          Query query = qService.newQuery(queryString[0]);
+          results = (SelectResults) query.execute();
+        } catch (Exception e) {
+          Assert.fail("Failed executing " + queryString[0], e);
+        }
+        assertEquals(numberOfEntries, results.size());
+      }
+    };
+
+    vm3.invoke(executeQueries);
+
+    // Check for TestObject instances on Server2.
+    // It should be 0
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query on compressed PdxInstance. The client receives 
uncompressed value.
+   */
+  @Test
+  public void testClientServerQueryWithCompression() throws CacheException {
+    final String randomString =
+        
"asddfjkhaskkfdjhzjc0943509328kvnhfjkldsg09q3485ibjafdp9q8y43p9u7hgavpiuaha48uy9afliasdnuaiuqa498qa4"
+            + 
"asddfjkhaskkfdjhzjc0943509328kvnhfjkldsg09q3485ibjafdp9q8y43p9u7hgavpiuaha48uy9afliasdnuaiuqa498qa4"
+            + 
"asddfjkhaskkfdjhzjc0943509328kvnhfjkldsg09q3485ibjafdp9q8y43p9u7hgavpiuaha48uy9afliasdnuaiuqa498qa4"
+            + 
"asddfjkhaskkfdjhzjc0943509328kvnhfjkldsg09q3485ibjafdp9q8y43p9u7hgavpiuaha48uy9afliasdnuaiuqa498qa4";
+
+    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;
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(false, false, false, compressor);
+        Region region = getRootRegion().getSubregion(regionName);
+        assert (region.getAttributes().getCompressor() != null);
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, randomString));
+        }
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        System.out.println("##### Region size is: " + region.size());
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    // Create client region
+    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 = "testClientServerQueriesWithParamsPool";
+    createPool(vm2, poolName, new String[] {host0}, new int[] {port0}, true);
+    createPool(vm3, poolName, new String[] {host0}, new int[] {port1}, true);
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      @SuppressWarnings("unchecked")
+      public void run2() throws CacheException {
+        SelectResults<String> results = null;
+        QueryService qService = null;
+        try {
+          qService = (PoolManager.find(poolName)).getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+        try {
+          logger.info("### Executing Query :" + queryString[2]);
+          Query query = qService.newQuery(queryString[2]);
+          results = (SelectResults<String>) query.execute();
+        } catch (Exception e) {
+          Assert.fail("Failed executing " + queryString[2], e);
+        }
+        assertEquals(numberOfEntries, results.size());
+        for (String result : results) {
+          assertEquals(randomString, result);
+        }
+      }
+    };
+
+    vm3.invoke(executeQueries);
+
+    // Check for TestObject instances on Server2.
+    // It should be 0
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query on PdxInstance. The client receives projected 
value.
+   */
+  @Test
+  public void testVersionedClass() 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;
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        try {
+          for (int i = 0; i < numberOfEntries; i++) {
+            PdxInstanceFactory pdxFactory =
+                PdxInstanceFactoryImpl.newCreator("PdxTestObject", false);
+            pdxFactory.writeInt("id", i);
+            pdxFactory.writeString("ticker", "vmware");
+            pdxFactory.writeString("idTickers", i + "vmware");
+            PdxInstance pdxInstance = pdxFactory.create();
+            region.put("key-" + i, pdxInstance);
+          }
+        } catch (Exception ex) {
+          Assert.fail("Failed to load the class.", ex);
+        }
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        System.out.println("##### Region size is: " + region.size());
+        assertEquals(0, TestObject.numInstance);
+
+      }
+    });
+
+    // Create client region
+    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 = "testClientServerQueriesWithParamsPool";
+    createPool(vm2, poolName, new String[] {host0}, new int[] {port0}, true);
+    createPool(vm3, poolName, new String[] {host0}, new int[] {port1}, true);
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        SelectResults results = null;
+        QueryService qService = null;
+        try {
+          qService = (PoolManager.find(poolName)).getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+        try {
+          logger.info("### Executing Query :" + queryString[0]);
+          Query query = qService.newQuery(queryString[0]);
+          results = (SelectResults) query.execute();
+        } catch (Exception e) {
+          Assert.fail("Failed executing " + queryString[0], e);
+        }
+
+        assertEquals(numberOfEntries, results.size());
+      }
+    };
+
+    vm3.invoke(executeQueries);
+
+    // Check for TestObject instances on Server2.
+    // It should be 0
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query on PdxInstance.
+   */
+  @Test
+  public void testClientServerQuery() 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;
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      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);
+
+    // Create client region
+    vm3.invoke(new CacheSerializableRunnable("Create region") {
+      public void run2() throws CacheException {
+        QueryService localQueryService = null;
+
+        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());
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+
+        // Execute query locally.
+        try {
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+        for (int i = 0; i < 3; i++) {
+          try {
+            Query query = localQueryService.newQuery(queryString[i]);
+            SelectResults results = (SelectResults) query.execute();
+            assertEquals(numberOfEntries, results.size());
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queryString[i], e);
+          }
+        }
+      }
+    });
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        QueryService remoteQueryService = null;
+        QueryService localQueryService = null;
+        SelectResults[][] rs = new SelectResults[1][2];
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 1; i < 3; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queryString[i]);
+            Query query = remoteQueryService.newQuery(queryString[i]);
+            rs[0][0] = (SelectResults) query.execute();
+            assertEquals(numberOfEntries, rs[0][0].size());
+
+            logger.info("### Executing Query locally:" + queryString[i]);
+            query = localQueryService.newQuery(queryString[i]);
+            rs[0][1] = (SelectResults) query.execute();
+            assertEquals(numberOfEntries, rs[0][1].size());
+
+            // Compare local and remote query results.
+            if (!CacheUtils.compareResultsOfWithAndWithoutIndex(rs)) {
+              fail("Local and Remote Query Results are not matching for query 
:" + queryString[i]);
+            }
+
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queryString[i], e);
+          }
+
+        }
+        assertEquals(2 * numberOfEntries, TestObject.numInstance);
+      }
+    };
+
+    vm3.invoke(executeQueries);
+
+    // Check for TestObject instances on Server2.
+    // It should be 0
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query on PdxInstance.
+   */
+  @Test
+  public void testClientServerQueryWithRangeIndex() 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 String[] qs = new String[] {"SELECT * FROM " + regName + " p WHERE 
p.ID > 0",
+        "SELECT p FROM " + regName + " p WHERE p.ID > 0",
+        "SELECT * FROM " + regName + " p WHERE p.ID = 1",
+        "SELECT * FROM " + regName + " p WHERE p.ID < 10",
+        "SELECT * FROM " + regName + " p WHERE p.ID != 10",
+        "SELECT * FROM " + regName + " p, p.positions.values pos WHERE p.ID > 
0",
+        "SELECT * FROM " + regName + " p, p.positions.values pos WHERE p.ID = 
10",
+        "SELECT p, pos FROM " + regName + " p, p.positions.values pos WHERE 
p.ID > 0",
+        "SELECT p, pos FROM " + regName + " p, p.positions.values pos WHERE 
p.ID = 10",
+        "SELECT pos FROM " + regName + " p, p.positions.values pos WHERE p.ID 
> 0",
+        "SELECT p, pos FROM " + regName + " p, p.positions.values pos WHERE 
pos.secId != 'XXX'",
+        "SELECT pos FROM " + regName + " p, p.positions.values pos WHERE 
pos.secId != 'XXX'",
+        "SELECT pos FROM " + regName + " p, p.positions.values pos WHERE 
pos.secId = 'SUN'",
+        "SELECT p, pos FROM " + regName + " p, p.positions.values pos WHERE 
pos.secId = 'SUN'",
+        "SELECT p, pos FROM " + regName + " p, p.positions.values pos WHERE 
pos.secId = 'DELL'",
+        "SELECT * FROM " + regName + " p, p.positions.values pos WHERE 
pos.secId = 'SUN'",
+        "SELECT * FROM " + regName + " p, p.positions.values pos WHERE 
pos.secId = 'DELL'",
+        "SELECT p, p.position1 FROM " + regName + " p where p.position1.secId 
!= 'XXX'",
+        "SELECT p, p.position1 FROM " + regName + " p where p.position1.secId 
= 'SUN'",
+        "SELECT p.position1 FROM " + regName + " p WHERE p.ID > 0",
+        "SELECT * FROM " + regName + " p WHERE p.status = 'active'",
+        "SELECT p FROM " + regName + " p WHERE p.status != 'active'",};
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(false, false, true, null); // Async index
+        Region region = getRootRegion().getSubregion(regionName);
+        // Create Range index.
+        QueryService qs = getCache().getQueryService();
+        try {
+          qs.createIndex("idIndex", "p.ID", regName + " p");
+          qs.createIndex("statusIndex", "p.status", regName + " p");
+          qs.createIndex("secIdIndex", "pos.secId", regName + " p, 
p.positions.values pos");
+          qs.createIndex("pSecIdIdIndex", "p.position1.secId", regName + " p");
+        } catch (Exception ex) {
+          fail("Failed to create index." + ex.getMessage());
+        }
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(false, false, true, null); // Async index
+        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);
+
+    // Create client region
+    vm3.invoke(new CacheSerializableRunnable("Create region") {
+      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 < 100; i++) {
+          region.put("key-" + i, new PortfolioPdx(j, j++));
+          // To add duplicate:
+          if (i % 24 == 0) {
+            j = 0; // reset
+          }
+        }
+      }
+    });
+
+
+    // Execute query and make sure there is no PdxInstance in the results.
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        // Execute query locally.
+        QueryService queryService = getCache().getQueryService();
+        for (int i = 0; i < qs.length; i++) {
+          try {
+            Query query = queryService.newQuery(qs[i]);
+            SelectResults results = (SelectResults) query.execute();
+            for (Object o : results.asList()) {
+              if (o instanceof Struct) {
+                Object[] values = ((Struct) o).getFieldValues();
+                for (int c = 0; c < values.length; c++) {
+                  if (values[c] instanceof PdxInstance) {
+                    fail("Found unexpected PdxInstance in the query results. 
At struct field [" + c
+                        + "] query :" + qs[i] + " Object is: " + values[c]);
+                  }
+                }
+              } else {
+                if (o instanceof PdxInstance) {
+                  fail("Found unexpected PdxInstance in the query results. " + 
qs[i]);
+                }
+              }
+            }
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + qs[i], e);
+          }
+
+        }
+      }
+    });
+
+    // Re-execute query to fetch PdxInstance in the results.
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        // Execute query locally.
+        GemFireCacheImpl cache = (GemFireCacheImpl) getCache();
+        cache.setReadSerialized(true);
+        try {
+          QueryService queryService = getCache().getQueryService();
+          for (int i = 0; i < qs.length; i++) {
+            try {
+              Query query = queryService.newQuery(qs[i]);
+              SelectResults results = (SelectResults) query.execute();
+              for (Object o : results.asList()) {
+                if (o instanceof Struct) {
+                  Object[] values = ((Struct) o).getFieldValues();
+                  for (int c = 0; c < values.length; c++) {
+                    if (!(values[c] instanceof PdxInstance)) {
+                      fail(
+                          "Didn't found expected PdxInstance in the query 
results. At struct field ["
+                              + c + "] query :" + qs[i] + " Object is: " + 
values[c]);
+                    }
+                  }
+                } else {
+                  if (!(o instanceof PdxInstance)) {
+                    fail("Didn't found expected PdxInstance in the query 
results. " + qs[i]
+                        + " Object is: " + o);
+                  }
+                }
+              }
+            } catch (Exception e) {
+              Assert.fail("Failed executing " + qs[i], e);
+            }
+          }
+        } finally {
+          cache.setReadSerialized(false);
+        }
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query on PdxInstance.
+   */
+  @Test
+  public void testClientServerCountQuery() 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 = "SELECT COUNT(*) FROM " + regName + " WHERE id >= 
0";
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      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);
+
+    // Create client region
+    vm3.invoke(new CacheSerializableRunnable("Create region") {
+      public void run2() throws CacheException {
+        QueryService localQueryService = null;
+
+        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());
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+
+        // Execute query locally.
+        try {
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+        try {
+          Query query = localQueryService.newQuery(queryStr);
+          SelectResults results = (SelectResults) query.execute();
+          assertEquals(numberOfEntries, ((Integer) 
results.asList().get(0)).intValue());
+        } catch (Exception e) {
+          Assert.fail("Failed executing " + queryStr, e);
+        }
+
+      }
+    });
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        QueryService remoteQueryService = null;
+        QueryService localQueryService = null;
+        SelectResults[][] rs = new SelectResults[1][2];
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        try {
+          logger.info("### Executing Query on server:" + queryStr);
+          Query query = remoteQueryService.newQuery(queryStr);
+          rs[0][0] = (SelectResults) query.execute();
+          assertEquals(numberOfEntries, ((Integer) 
rs[0][0].asList().get(0)).intValue());
+
+          logger.info("### Executing Query locally:" + queryStr);
+          query = localQueryService.newQuery(queryStr);
+          rs[0][1] = (SelectResults) query.execute();
+          assertEquals(numberOfEntries, ((Integer) 
rs[0][1].asList().get(0)).intValue());
+
+          // Compare local and remote query results.
+          if (!CacheUtils.compareResultsOfWithAndWithoutIndex(rs)) {
+            fail("Local and Remote Query Results are not matching for query :" 
+ queryStr);
+          }
+
+        } catch (Exception e) {
+          Assert.fail("Failed executing " + queryStr, e);
+        }
+
+        assertEquals(numberOfEntries, TestObject.numInstance);
+      }
+    };
+
+    vm3.invoke(executeQueries);
+
+    // Check for TestObject instances on Server2.
+    // It should be 0
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query on PdxInstance.
+   */
+  @Test
+  public void testVersionedClientServerQuery() 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 DISTINCT ID FROM " + 
regName, // 0
+        "SELECT * FROM " + regName, // 1
+        "SELECT pkid FROM " + regName, // 2
+        "SELECT * FROM " + regName + " WHERE ID > 5", // 3
+        "SELECT p FROM " + regName + " p, p.positions pos WHERE p.pkid != 
'vmware'", // 4
+        "SELECT entry.value FROM " + this.regName + ".entries entry WHERE 
entry.value.ID > 0",
+        "SELECT entry.value FROM  " + this.regName + ".entries entry WHERE 
entry.key = 'key-1'",
+        "SELECT e.value FROM " + this.regName + ".entrySet e where  
e.value.pkid >= '0'",
+        "SELECT * FROM " + this.regName + ".values p WHERE p.pkid in SET('1', 
'2','3')",
+        "SELECT * FROM " + this.regName + " pf where pf.position1.secId > '2'",
+        "SELECT * FROM " + this.regName + " p where p.position3[1].portfolioId 
= 2",
+        "SELECT * FROM " + this.regName + " p, p.positions.values AS pos WHERE 
pos.secId != '1'",
+        "SELECT key, positions FROM " + this.regName + ".entrySet, 
value.positions.values "
+            + "positions WHERE positions.mktValue >= 25.00",
+        "SELECT * FROM " + this.regName + " portfolio1, " + this.regName + " 
portfolio2 WHERE "
+            + "portfolio1.status = portfolio2.status",
+        "SELECT portfolio1.ID, portfolio2.status FROM " + this.regName + " 
portfolio1, "
+            + this.regName + " portfolio2  WHERE portfolio1.status = 
portfolio2.status",
+        "SELECT * FROM " + this.regName + " portfolio1, 
portfolio1.positions.values positions1, "
+            + this.regName + " portfolio2,  portfolio2.positions.values 
positions2 WHERE "
+            + "positions1.secId = positions1.secId ",
+        "SELECT * FROM " + this.regName + " portfolio, 
portfolio.positions.values positions WHERE "
+            + "portfolio.Pk IN SET ('1', '2') AND positions.secId = '1'",
+        "SELECT DISTINCT pf1, pf2 FROM " + this.regName
+            + "  pf1, pf1.collectionHolderMap.values coll1," + " 
pf1.positions.values posit1, "
+            + this.regName + "  pf2, pf2.collectionHolderMap.values "
+            + " coll2, pf2.positions.values posit2 WHERE pf1.ID = pf2.ID",};
+
+
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      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);
+
+    // Create client region
+    vm3.invoke(new CacheSerializableRunnable("Create region") {
+      public void run2() throws CacheException {
+
+        // Load client/server region.
+        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());
+
+        try {
+
+          // Load TestObject
+          for (int i = 0; i < numberOfEntries; i++) {
+            PortfolioPdxVersion portfolioPdxVersion =
+                new PortfolioPdxVersion(new Integer(i), new Integer(i));
+            PdxInstanceFactory pdxFactory =
+                PdxInstanceFactoryImpl.newCreator("PortfolioPdxVersion", 
false);
+            PdxInstance pdxInstance = 
portfolioPdxVersion.createPdxInstance(pdxFactory);
+            region.put("key-" + i, pdxInstance);
+          }
+        } catch (Exception ex) {
+          fail("Failed to load the class.");
+        }
+
+        // Execute query:
+        QueryService remoteQueryService = null;
+        QueryService localQueryService = null;
+        SelectResults[][] rs = new SelectResults[1][2];
+
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 0; i < queryStr.length; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queryStr[i]);
+            Query query = remoteQueryService.newQuery(queryStr[i]);
+            rs[0][0] = (SelectResults) query.execute();
+            logger.info("### Executing Query locally:" + queryStr[i]);
+            query = localQueryService.newQuery(queryStr[i]);
+            rs[0][1] = (SelectResults) query.execute();
+            logger.info("### Remote Query rs size: " + (rs[0][0]).size() + 
"Local Query rs size: "
+                + (rs[0][1]).size());
+            // Compare local and remote query results.
+            if (!CacheUtils.compareResultsOfWithAndWithoutIndex(rs)) {
+              fail("Local and Remote Query Results are not matching for query 
:" + queryStr[i]);
+            }
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queryStr[i], e);
+          }
+
+        }
+
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query on PdxInstance with mixed types.
+   */
+  @Test
+  public void testClientServerQueryMixedTypes() throws CacheException {
+
+    final String[] testQueries = new String[] {"select ticker from /root/" + 
regionName,
+        "select ticker from /root/" + regionName + " p where 
IS_DEFINED(p.ticker)",
+        "select ticker from /root/" + regionName + " where ticker = 
'vmware'",};
+    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;
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+        for (int i = numberOfEntries; i < (numberOfEntries + 10); i++) {
+          region.put("key-" + i, new TestObject2(i));
+        }
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      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);
+
+    // Create client region
+    vm3.invoke(new CacheSerializableRunnable("Create region") {
+      public void run2() throws CacheException {
+        QueryService localQueryService = null;
+
+        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());
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+        for (int i = numberOfEntries; i < (numberOfEntries + 10); i++) {
+          region.put("key-" + i, new TestObject2(i));
+        }
+        // Execute query locally.
+        try {
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+        for (int i = 0; i < 3; i++) {
+          try {
+            Query query = localQueryService.newQuery(testQueries[i]);
+            SelectResults results = (SelectResults) query.execute();
+            if (i == 0) {
+              assertEquals(numberOfEntries + 10, results.size());
+            } else {
+              assertEquals(numberOfEntries, results.size());
+            }
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + testQueries[i], e);
+          }
+        }
+      }
+    });
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        QueryService remoteQueryService = null;
+        QueryService localQueryService = null;
+        SelectResults[][] rs = new SelectResults[1][2];
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 0; i < 3; i++) {
+          try {
+            logger.info("### Executing Query on server:" + testQueries[i]);
+            Query query = remoteQueryService.newQuery(testQueries[i]);
+            rs[0][0] = (SelectResults) query.execute();
+            if (i == 0) {
+              // defined and undefined values returned
+              assertEquals(numberOfEntries + 10, rs[0][0].size());
+            } else {
+              // only defined values of ticker
+              assertEquals(numberOfEntries, rs[0][0].size());
+            }
+            logger.info("### Executing Query locally:" + testQueries[i]);
+            query = localQueryService.newQuery(testQueries[i]);
+            rs[0][1] = (SelectResults) query.execute();
+            if (i == 0) {
+              assertEquals(numberOfEntries + 10, rs[0][1].size());
+            } else {
+              assertEquals(numberOfEntries, rs[0][1].size());
+            }
+            assertEquals(rs[0][0].size(), rs[0][1].size());
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + testQueries[i], e);
+          }
+
+        }
+        assertEquals(2 * (numberOfEntries + 5), (TestObject.numInstance + 
TestObject2.numInstance));
+      }
+    };
+
+    vm3.invoke(executeQueries);
+
+    // Check for TestObject instances on Server2.
+    // It should be 0
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests query on with PR.
+   */
+  @Test
+  public void testQueryOnPR() 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 = 100;
+
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, true);
+      }
+    });
+
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, false);
+      }
+    });
+
+    vm2.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, false);
+      }
+    });
+
+    // Load region.
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        Region region = getRootRegion().getSubregion(regionName);
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+      }
+    });
+
+    // Client pool.
+    final int port1 = vm1.invoke(() -> PdxQueryDUnitTest.getCacheServerPort());
+
+    final String host0 = NetworkUtils.getServerHostName(vm0.getHost());
+
+    // Create client pool.
+    final String poolName = "testClientServerQueryPool";
+    createPool(vm3, poolName, new String[] {host0}, new int[] {port1}, true);
+
+    // Execute client queries
+    vm3.invoke(new CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        QueryService remoteQueryService = null;
+
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 1; i < 3; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queryString[i]);
+            Query query = remoteQueryService.newQuery(queryString[i]);
+            SelectResults rs = (SelectResults) query.execute();
+            assertEquals(numberOfEntries, rs.size());
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queryString[i], e);
+          }
+        }
+        assertEquals(numberOfEntries, TestObject.numInstance);
+      }
+    });
+
+    // Check for TestObject instances.
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(numberOfEntries, TestObject.numInstance);
+      }
+    });
+
+    // Check for TestObject instances.
+    // It should be 0
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    // Check for TestObject instances.
+    // It should be 0
+    vm2.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    // Execute Query on Server2.
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        QueryService qs = getCache().getQueryService();
+        Query query = null;
+        SelectResults sr = null;
+        for (int i = 0; i < queryString.length; i++) {
+          try {
+            query = qs.newQuery(queryString[i]);
+            sr = (SelectResults) query.execute();
+          } catch (Exception ex) {
+            fail("Failed to execute query, " + ex.getMessage());
+          }
+
+          for (Object o : sr.asSet()) {
+            if (i == 0 && !(o instanceof Integer)) {
+              fail("Expected type Integer, not found in result set. Found type 
:" + o.getClass());
+            } else if (i == 1 && !(o instanceof TestObject)) {
+              fail(
+                  "Expected type TestObject, not found in result set. Found 
type :" + o.getClass());
+            } else if (i == 2 && !(o instanceof String)) {
+              fail("Expected type String, not found in result set. Found type 
:" + o.getClass());
+            }
+          }
+        }
+        if (TestObject.numInstance <= 0) {
+          fail("Expected TestObject instance to be >= 0.");
+        }
+      }
+    });
+
+    // Check for TestObject instances.
+    // It should be 0
+    vm2.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests query on with PR.
+   */
+  @Test
+  public void testLocalPRQuery() 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 = 100;
+
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, true);
+      }
+    });
+
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, false);
+      }
+    });
+
+    vm2.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, false);
+      }
+    });
+
+    vm3.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, false);
+      }
+    });
+
+
+    // Load region using class loader and execute query on the same thread.
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        Region region = getRootRegion().getSubregion(regionName);
+        try {
+          // Load TestObject
+          for (int i = 0; i < numberOfEntries; i++) {
+            PdxInstanceFactory pdxInstanceFactory =
+                PdxInstanceFactoryImpl.newCreator("PortfolioPdxVersion", 
false);
+            PortfolioPdxVersion portfolioPdxVersion =
+                new PortfolioPdxVersion(new Integer(i), new Integer(i));
+            PdxInstance pdxInstance = 
portfolioPdxVersion.createPdxInstance(pdxInstanceFactory);
+            region.put("key-" + i, pdxInstance);
+          }
+        } catch (Exception ex) {
+          Assert.fail("Failed to load the class.", ex);
+        }
+
+        QueryService localQueryService = null;
+
+        try {
+          localQueryService = region.getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 1; i < 3; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queryString[i]);
+            Query query = localQueryService.newQuery(queryString[i]);
+            SelectResults rs = (SelectResults) query.execute();
+            assertEquals(numberOfEntries, rs.size());
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queryString[i], e);
+          }
+        }
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests query on with PR.
+   */
+  @Test
+  public void testPdxReadSerializedForPRQuery() 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 = 100;
+
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, true);
+      }
+    });
+
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, false);
+      }
+    });
+
+    vm2.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, false);
+      }
+    });
+
+    vm3.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(true, false);
+      }
+    });
+
+
+    // Load region using class loader and execute query on the same thread.
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        Region region = getRootRegion().getSubregion(regionName);
+        try {
+          // Load TestObject
+          for (int i = 0; i < numberOfEntries; i++) {
+            PortfolioPdxVersion portfolioPdxVersion =
+                new PortfolioPdxVersion(new Integer(i), new Integer(i));
+            PdxInstanceFactory pdxInstanceFactory =
+                PdxInstanceFactoryImpl.newCreator("PortfolioPdxVersion", 
false);
+            PdxInstance pdxInstance = 
portfolioPdxVersion.createPdxInstance(pdxInstanceFactory);
+            region.put("key-" + i, pdxInstance);
+          }
+        } catch (Exception ex) {
+          fail("Failed to load the class.");
+        }
+
+        QueryService localQueryService = null;
+
+        try {
+          localQueryService = region.getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 1; i < 3; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queryString[i]);
+            Query query = localQueryService.newQuery(queryString[i]);
+            SelectResults rs = (SelectResults) query.execute();
+            assertEquals(numberOfEntries, rs.size());
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queryString[i], e);
+          }
+        }
+      }
+    });
+
+    final String[] qs = new String[] {"SELECT * FROM " + regName,
+        "SELECT * FROM " + regName + " WHERE ID > 5", "SELECT p FROM " + 
regName
+            + " p, p.positions.values pos WHERE p.ID > 2 or pos.secId = 
'vmware'",};
+
+    // Execute query on node without class and with pdxReadSerialized.
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        Region region = getRootRegion().getSubregion(regionName);
+        GemFireCacheImpl c = (GemFireCacheImpl) region.getCache();
+        try {
+          // Set read serialized.
+          c.setReadSerialized(true);
+
+          QueryService localQueryService = null;
+
+          try {
+            localQueryService = region.getCache().getQueryService();
+          } catch (Exception e) {
+            Assert.fail("Failed to get QueryService.", e);
+          }
+
+          // This should not throw class not found exception.
+          for (int i = 1; i < qs.length; i++) {
+            try {
+              logger.info("### Executing Query on server:" + qs[i]);
+              Query query = localQueryService.newQuery(qs[i]);
+              SelectResults rs = (SelectResults) query.execute();
+              for (Object o : rs.asSet()) {
+                if (!(o instanceof PdxInstance)) {
+                  fail("Expected type PdxInstance, not found in result set. 
Found type :"
+                      + o.getClass());
+                }
+              }
+            } catch (Exception e) {
+              Assert.fail("Failed executing " + qs[i], e);
+            }
+          }
+        } finally {
+          c.setReadSerialized(false);
+        }
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+
+  /**
+   * Tests index on PdxInstance.
+   */
+  @Test
+  public void testIndex() 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;
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        for (int i = 0; i < numberOfEntries; i++) {
+          if (i % 2 == 0) {
+            region.put("key-" + i, new TestObject(i, "vmware"));
+          } else {
+            region.put("key-" + i, new TestObject(i, "vmware" + i));
+          }
+        }
+
+        try {
+          QueryService qs = getCache().getQueryService();
+          qs.createIndex("idIndex", IndexType.FUNCTIONAL, "id", regName);
+          qs.createIndex("tickerIndex", IndexType.FUNCTIONAL, "p.ticker", 
regName + " p");
+          qs.createIndex("tickerIdTickerMapIndex", IndexType.FUNCTIONAL, 
"p.ticker",
+              regName + " p, p.idTickers idTickers");
+        } catch (Exception ex) {
+          fail("Unable to create index. " + ex.getMessage());
+        }
+        assertEquals(numberOfEntries, TestObject.numInstance);
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+
+        try {
+          QueryService qs = getCache().getQueryService();
+          qs.createIndex("idIndex", IndexType.FUNCTIONAL, "id", regName);
+          qs.createIndex("tickerIndex", IndexType.FUNCTIONAL, "p.ticker", 
regName + " p");
+          qs.createIndex("tickerIdTickerMapIndex", IndexType.FUNCTIONAL, 
"p.ticker",
+              regName + " p, p.idTickers idTickers");
+        } catch (Exception ex) {
+          fail("Unable to create index. " + ex.getMessage());
+        }
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    // 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);
+
+    // Create client region
+    SerializableRunnable createClientRegions = new 
CacheSerializableRunnable("Create region") {
+      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());
+        for (int i = 0; i < numberOfEntries * 2; i++) {
+          if (i % 2 == 0) {
+            region.put("key-" + i, new TestObject(i, "vmware"));
+          } else {
+            region.put("key-" + i, new TestObject(i, "vmware" + i));
+          }
+        }
+      }
+    };
+
+    vm2.invoke(createClientRegions);
+    vm3.invoke(createClientRegions);
+
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(numberOfEntries, TestObject.numInstance);
+      }
+    });
+
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        QueryService remoteQueryService = null;
+        QueryService localQueryService = null;
+        SelectResults[][] rs = new SelectResults[1][2];
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 0; i < 3; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queryString[i]);
+            Query query = remoteQueryService.newQuery(queryString[i]);
+            rs[0][0] = (SelectResults) query.execute();
+            assertEquals(numberOfEntries * 2, rs[0][0].size());
+
+            logger.info("### Executing Query locally:" + queryString[i]);
+            query = localQueryService.newQuery(queryString[i]);
+            rs[0][1] = (SelectResults) query.execute();
+            assertEquals(numberOfEntries * 2, rs[0][1].size());
+
+            // Compare local and remote query results.
+            if (!CacheUtils.compareResultsOfWithAndWithoutIndex(rs)) {
+              fail("Local and Remote Query Results are not matching for query 
:" + queryString[i]);
+            }
+
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queryString[i], e);
+          }
+
+        }
+        assertEquals(4 * numberOfEntries, TestObject.numInstance);
+
+        for (int i = 3; i < queryString.length; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queryString[i]);
+            Query query = remoteQueryService.newQuery(queryString[i]);
+            rs[0][0] = (SelectResults) query.execute();
+
+            logger.info("### Executing Query locally:" + queryString[i]);
+            query = localQueryService.newQuery(queryString[i]);
+            rs[0][1] = (SelectResults) query.execute();
+
+            // Compare local and remote query results.
+            if (!CacheUtils.compareResultsOfWithAndWithoutIndex(rs)) {
+              fail("Local and Remote Query Results are not matching for query 
:" + queryString[i]);
+            }
+
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queryString[i], e);
+          }
+
+        }
+
+      }
+    };
+
+    vm2.invoke(executeQueries);
+    vm3.invoke(executeQueries);
+
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(numberOfEntries, TestObject.numInstance);
+      }
+    });
+
+    // Check for TestObject instances on Server2.
+    // It should be 0
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query with region iterators.
+   */
+  @Test
+  public void testRegionIterators() 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[] queries = new String[] {
+        "SELECT entry.value FROM " + this.regName + ".entries entry WHERE 
entry.value.id > 0",
+        "SELECT entry.value FROM  " + this.regName + ".entries entry WHERE 
entry.key = 'key-1'",
+        "SELECT e.value FROM " + this.regName + ".entrySet e where  e.value.id 
>= 0",
+        "SELECT * FROM " + this.regName + ".values p WHERE p.ticker = 
'vmware'",};
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      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);
+
+    // Create client region
+    vm3.invoke(new CacheSerializableRunnable("Create region") {
+      public void run2() throws CacheException {
+        QueryService localQueryService = null;
+
+        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());
+        for (int i = 0; i < numberOfEntries; i++) {
+          region.put("key-" + i, new TestObject(i, "vmware"));
+        }
+      }
+    });
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        QueryService remoteQueryService = null;
+        QueryService localQueryService = null;
+        SelectResults[][] rs = new SelectResults[1][2];
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 0; i < queries.length; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queries[i]);
+            Query query = remoteQueryService.newQuery(queries[i]);
+            rs[0][0] = (SelectResults) query.execute();
+
+            logger.info("### Executing Query locally:" + queries[i]);
+            query = localQueryService.newQuery(queries[i]);
+            rs[0][1] = (SelectResults) query.execute();
+
+            // Compare local and remote query results.
+            if (!CacheUtils.compareResultsOfWithAndWithoutIndex(rs)) {
+              fail("Local and Remote Query Results are not matching for query 
:" + queries[i]);
+            }
+
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queries[i], e);
+          }
+
+        }
+      }
+    };
+
+    vm3.invoke(executeQueries);
+
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+
+    // Create index
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        Region region = getRootRegion().getSubregion(regionName);
+        QueryService qs = getCache().getQueryService();
+        try {
+          qs.createIndex("idIndex", IndexType.FUNCTIONAL, "entry.value.id",
+              regName + ".entries entry");
+          qs.createIndex("tickerIndex", IndexType.FUNCTIONAL, "p.ticker", 
regName + ".values p");
+        } catch (Exception ex) {
+          fail("Unable to create index. " + ex.getMessage());
+        }
+      }
+    });
+
+    vm3.invoke(executeQueries);
+
+    // Check for TestObject instances.
+    // It should be 0
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, TestObject.numInstance);
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query with nested and collection of Pdx.
+   */
+  @Test
+  public void testNestedAndCollectionPdx() 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 = 50;
+
+    final String[] queries = new String[] {
+        "SELECT * FROM " + this.regName + " pf where pf.position1.secId > '2'",
+        "SELECT * FROM " + this.regName + " p where p.position3[1].portfolioId 
= 2",
+        "SELECT * FROM " + this.regName + " p, p.positions.values AS pos WHERE 
pos.secId != '1'",
+        "SELECT key, positions FROM " + this.regName + ".entrySet, 
value.positions.values "
+            + "positions WHERE positions.mktValue >= 25.00",
+        "SELECT * FROM " + this.regName + " portfolio1, " + this.regName2 + " 
portfolio2 WHERE "
+            + "portfolio1.status = portfolio2.status",
+        "SELECT portfolio1.ID, portfolio2.status FROM " + this.regName + " 
portfolio1, "
+            + this.regName + " portfolio2  WHERE portfolio1.status = 
portfolio2.status",
+        "SELECT * FROM " + this.regName + " portfolio1, 
portfolio1.positions.values positions1, "
+            + this.regName + " portfolio2,  portfolio2.positions.values 
positions2 WHERE "
+            + "positions1.secId = positions2.secId ",
+        "SELECT * FROM " + this.regName + " portfolio, 
portfolio.positions.values positions WHERE "
+            + "portfolio.Pk IN SET ('1', '2') AND positions.secId = '1'",
+        "SELECT DISTINCT * FROM " + this.regName + "  pf1, 
pf1.collectionHolderMap.values coll1,"
+            + " pf1.positions.values posit1, " + this.regName2
+            + "  pf2, pf2.collectionHolderMap.values "
+            + " coll2, pf2.positions.values posit2 WHERE posit1.secId='IBM' 
AND posit2.secId='IBM'",};
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region1 = getRootRegion().getSubregion(regionName);
+        Region region2 = getRootRegion().getSubregion(regionName2);
+
+        for (int i = 0; i < numberOfEntries; i++) {
+          region1.put("key-" + i, new PortfolioPdx(i, i));
+          region2.put("key-" + i, new PortfolioPdx(i, i));
+        }
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+        Region region2 = getRootRegion().getSubregion(regionName2);
+      }
+    });
+
+
+    // 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);
+
+    // Create client region
+    vm3.invoke(new CacheSerializableRunnable("Create region") {
+      public void run2() throws CacheException {
+
+        AttributesFactory factory = new AttributesFactory();
+        factory.setScope(Scope.LOCAL);
+        ClientServerTestCase.configureConnectionPool(factory, host0, port1, 
-1, true, -1, -1, null);
+        Region region1 = createRegion(regionName, rootRegionName, 
factory.create());
+        Region region2 = createRegion(regionName2, rootRegionName, 
factory.create());
+
+        for (int i = 0; i < numberOfEntries; i++) {
+          region1.put("key-" + i, new PortfolioPdx(i, i));
+          region2.put("key-" + i, new PortfolioPdx(i, i));
+        }
+      }
+    });
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        QueryService remoteQueryService = null;
+        QueryService localQueryService = null;
+        SelectResults[][] rs = new SelectResults[1][2];
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 0; i < queries.length; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queries[i]);
+            Query query = remoteQueryService.newQuery(queries[i]);
+            rs[0][0] = (SelectResults) query.execute();
+
+            logger.info("### Executing Query locally:" + queries[i]);
+            query = localQueryService.newQuery(queries[i]);
+            rs[0][1] = (SelectResults) query.execute();
+
+            // Compare local and remote query results.
+            if (!CacheUtils.compareResultsOfWithAndWithoutIndex(rs)) {
+              fail("Local and Remote Query Results are not matching for query 
:" + queries[i]);
+            }
+
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queries[i], e);
+          }
+
+        }
+      }
+    };
+
+    vm3.invoke(executeQueries);
+
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, PortfolioPdx.numInstance);
+        assertEquals(0, PositionPdx.numInstance);
+      }
+    });
+
+
+    // Create index
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        Region region = getRootRegion().getSubregion(regionName);
+        QueryService qs = getCache().getQueryService();
+        try {
+          qs.createIndex("pkIndex", IndexType.FUNCTIONAL, "portfolio.Pk", 
regName + " portfolio");
+          qs.createIndex("secIdIndex", IndexType.FUNCTIONAL, "pos.secId",
+              regName + " p, p.positions.values AS pos");
+          qs.createIndex("tickerIndex", IndexType.FUNCTIONAL, 
"pf.position1.secId",
+              regName + " pf");
+          qs.createIndex("secIdIndexPf1", IndexType.FUNCTIONAL, "pos11.secId",
+              regName + " pf1, pf1.collectionHolderMap.values coll1, 
pf1.positions.values pos11");
+          qs.createIndex("secIdIndexPf2", IndexType.FUNCTIONAL, "pos22.secId",
+              regName2 + " pf2, pf2.collectionHolderMap.values coll2, 
pf2.positions.values pos22");
+        } catch (Exception ex) {
+          fail("Unable to create index. " + ex.getMessage());
+        }
+      }
+    });
+
+    vm3.invoke(executeQueries);
+
+    // index is created on portfolio.Pk field which does not exists in
+    // PorfolioPdx object
+    // but there is a method getPk(), so for #44436, the objects are
+    // deserialized to get the value in vm1
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(numberOfEntries, PortfolioPdx.numInstance);
+        assertEquals(325, PositionPdx.numInstance); // 50 PorforlioPdx objects
+        // create (50*3)+50+50+50+25
+        // = 325 PositionPdx objects
+        // when deserialized
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+  /**
+   * Tests client-server query with nested and collection of Pdx.
+   */
+  @Test
+  public void testNestedAndCollectionPdxWithPR() 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 = 50;
+
+    final String[] queries = new String[] {
+        "SELECT * FROM " + this.regName + " pf where pf.position1.secId > '2'",
+        "SELECT * FROM " + this.regName + " p where p.position3[1].portfolioId 
= 2",
+        "SELECT * FROM " + this.regName + " p, p.positions.values AS pos WHERE 
pos.secId != '1'",
+        "SELECT key, positions FROM " + this.regName + ".entrySet, 
value.positions.values "
+            + "positions WHERE positions.mktValue >= 25.00",
+        "SELECT * FROM " + this.regName + " portfolio1, " + this.regName2 + " 
portfolio2 WHERE "
+            + "portfolio1.status = portfolio2.status",
+        "SELECT portfolio1.ID, portfolio2.status FROM " + this.regName + " 
portfolio1, "
+            + this.regName + " portfolio2  WHERE portfolio1.status = 
portfolio2.status",
+        "SELECT * FROM " + this.regName + " portfolio1, 
portfolio1.positions.values positions1, "
+            + this.regName + " portfolio2,  portfolio2.positions.values 
positions2 WHERE "
+            + "positions1.secId = positions2.secId ",
+        "SELECT * FROM " + this.regName + " portfolio, 
portfolio.positions.values positions WHERE "
+            + "portfolio.Pk IN SET ('1', '2') AND positions.secId = '1'",
+        "SELECT DISTINCT * FROM " + this.regName + "  pf1, 
pf1.collectionHolderMap.values coll1,"
+            + " pf1.positions.values posit1, " + this.regName2
+            + "  pf2, pf2.collectionHolderMap.values "
+            + " coll2, pf2.positions.values posit2 WHERE posit1.secId='IBM' 
AND posit2.secId='IBM'",};
+
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(false, true);
+        Region region1 = getRootRegion().getSubregion(regionName);
+        Region region2 = getRootRegion().getSubregion(regionName2);
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(false, true);
+        Region region = getRootRegion().getSubregion(regionName);
+        Region region2 = getRootRegion().getSubregion(regionName2);
+      }
+    });
+
+    // Start server2
+    vm2.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer(false, true);
+        Region region = getRootRegion().getSubregion(regionName);
+        Region region2 = getRootRegion().getSubregion(regionName2);
+      }
+    });
+
+    // 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);
+
+    // Create client region
+    vm3.invoke(new CacheSerializableRunnable("Create region") {
+      public void run2() throws CacheException {
+        QueryService localQueryService = null;
+
+        AttributesFactory factory = new AttributesFactory();
+        factory.setScope(Scope.LOCAL);
+        ClientServerTestCase.configureConnectionPool(factory, host0, port1, 
-1, true, -1, -1, null);
+        Region region1 = createRegion(regionName, rootRegionName, 
factory.create());
+        Region region2 = createRegion(regionName2, rootRegionName, 
factory.create());
+
+        for (int i = 0; i < numberOfEntries; i++) {
+          region1.put("key-" + i, new PortfolioPdx(i, i));
+          region2.put("key-" + i, new PortfolioPdx(i, i));
+        }
+      }
+    });
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        QueryService remoteQueryService = null;
+        QueryService localQueryService = null;
+        SelectResults[][] rs = new SelectResults[1][2];
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        for (int i = 0; i < queries.length; i++) {
+          try {
+            logger.info("### Executing Query on server:" + queries[i]);
+            Query query = remoteQueryService.newQuery(queries[i]);
+            rs[0][0] = (SelectResults) query.execute();
+
+            logger.info("### Executing Query locally:" + queries[i]);
+            query = localQueryService.newQuery(queries[i]);
+            rs[0][1] = (SelectResults) query.execute();
+
+            // Compare local and remote query results.
+            if (!CacheUtils.compareResultsOfWithAndWithoutIndex(rs)) {
+              fail("Local and Remote Query Results are not matching for query 
:" + queries[i]);
+            }
+
+          } catch (Exception e) {
+            Assert.fail("Failed executing " + queries[i], e);
+          }
+
+        }
+      }
+    };
+
+    vm3.invoke(executeQueries);
+
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, PortfolioPdx.numInstance);
+        assertEquals(0, PositionPdx.numInstance);
+      }
+    });
+
+
+    // Create index
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        Region region = getRootRegion().getSubregion(regionName);
+        QueryService qs = getCache().getQueryService();
+        try {
+          qs.createIndex("pkIndex", IndexType.FUNCTIONAL, "portfolio.Pk", 
regName + " portfolio");
+          qs.createIndex("idIndex", IndexType.FUNCTIONAL, "pos.secId",
+              regName + " p, p.positions.values AS pos");
+          qs.createIndex("tickerIndex", IndexType.FUNCTIONAL, 
"pf.position1.secId",
+              regName + " pf");
+          qs.createIndex("secIdIndexPf1", IndexType.FUNCTIONAL, "pos11.secId",
+              regName + " pf1, pf1.collectionHolderMap.values coll1, 
pf1.positions.values pos11");
+          qs.createIndex("secIdIndexPf2", IndexType.FUNCTIONAL, "pos22.secId",
+              regName2 + " pf2, pf2.collectionHolderMap.values coll2, 
pf2.positions.values pos22");
+        } catch (Exception ex) {
+          fail("Unable to create index. " + ex.getMessage());
+        }
+      }
+    });
+
+    vm3.invoke(executeQueries);
+
+    // Check for TestObject instances.
+    // It should be 0
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, PortfolioPdx.numInstance);
+        assertEquals(0, PositionPdx.numInstance);
+      }
+    });
+
+    // index is created on portfolio.Pk field which does not exists in
+    // PorfolioPdx object
+    // but there is a method getPk(), so for #44436, the objects are
+    // deserialized to get the value in vm1
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(numberOfEntries, PortfolioPdx.numInstance);
+        // 50 PorforlioPdx objects create (50*3)+50+50+50+25 = 325 PositionPdx
+        // objects when deserialized
+        assertEquals(325, PositionPdx.numInstance);
+      }
+    });
+
+    vm2.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        assertEquals(0, PortfolioPdx.numInstance);
+        assertEquals(0, PositionPdx.numInstance);
+      }
+    });
+
+    this.closeClient(vm2);
+    this.closeClient(vm3);
+    this.closeClient(vm1);
+    this.closeClient(vm0);
+  }
+
+
+
+  /**
+   * Tests identity of Pdx.
+   */
+  @Test
+  public void testPdxIdentity() 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 =
+        "SELECT DISTINCT * FROM " + this.regName + " pf where pf.ID > 2 and 
pf.ID < 10";
+    // Start server1
+    vm0.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      public void run2() throws CacheException {
+        configAndStartBridgeServer();
+        Region region = getRootRegion().getSubregion(regionName);
+      }
+    });
+
+    // Start server2
+    vm1.invoke(new CacheSerializableRunnable("Create Bridge Server") {
+      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") {
+      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 * 2; i++) {
+          // insert duplicate values.
+          if (i % dupIndex == 0) {
+            j++;
+          }
+          region.put("key-" + i, new PortfolioPdx(j));
+        }
+      }
+    });
+
+    // Execute client queries
+    SerializableRunnable executeQueries = new 
CacheSerializableRunnable("Execute queries") {
+      public void run2() throws CacheException {
+        QueryService remoteQueryService = null;
+        QueryService localQueryService = null;
+        SelectResults[][] rs = new SelectResults[1][2];
+        try {
+          remoteQueryService = (PoolManager.find(poolName)).getQueryService();
+          localQueryService = getCache().getQueryService();
+        } catch (Exception e) {
+          Assert.fail("Failed to get QueryService.", e);
+        }
+
+        int expectedResultSize = 7;
+
+        try {
+          logger.info("### Executing Query on server:" + queryStr);
+          Query query = remoteQueryService.newQuery(queryStr);
+  

<TRUNCATED>

Reply via email to