@Test
  public void testKeyMaintenance() throws Exception {

    final Host host = Host.getHost(0);
    VM server = host.getVM(0);
    VM client = host.getVM(1);

    cqDUnitTest.createServer(server);
    final int port = server.invoke(CqQueryUsingPoolDUnitTest::getCacheServerPort);
    final String host0 = NetworkUtils.getServerHostName(server.getHost());
    // cqDUnitTest.createClient(client, port, host0);

    String poolName = "testKeyMaintainance";
    cqDUnitTest.createPool(client, poolName, host0, port);

    // HashSet for caching purpose will be created for cqs.
    final int cqSize = 2;

    // Cq1
    cqDUnitTest.createCQ(client, poolName, "testKeyMaintainance_0", cqDUnitTest.cqs[0]);
    cqDUnitTest.executeCQ(client, "testKeyMaintainance_0", false, null);

    // Cq2
    cqDUnitTest.createCQ(client, poolName, "testKeyMaintainance_1", cqDUnitTest.cqs[10]);
    cqDUnitTest.executeCQ(client, "testKeyMaintainance_1", false, null);

    cqDUnitTest.createValues(server, cqDUnitTest.regions[0], 1);
    cqDUnitTest.waitForCreated(client, "testKeyMaintainance_0", CqQueryUsingPoolDUnitTest.KEY + 1);

    // Entry is made into the CQs cache hashset.
    // testKeyMaintainance_0 with 1 entry and testKeyMaintainance_1 with 0
    server.invoke(new CacheSerializableRunnable("LookForCachedEventKeys1") {
      @Override
      public void run2() throws CacheException {
        CqService cqService = null;
        try {
          cqService = ((DefaultQueryService) getCache().getQueryService()).getCqService();
        } catch (Exception ex) {
          LogWriterUtils.getLogWriter().info("Failed to get the internal CqService.", ex);
          Assert.fail("Failed to get the internal CqService.", ex);
        }

        Collection<? extends InternalCqQuery> cqs = cqService.getAllCqs();
        for (InternalCqQuery cq : cqs) {
          ServerCQImpl cqQuery = (ServerCQImpl) cq;

          String serverCqName = cqQuery.getServerCqName();
          if (serverCqName.startsWith("testKeyMaintainance_0")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_0 is wrong.", 1,
                cqQuery.getCqResultKeysSize());
          } else if (serverCqName.startsWith("testKeyMaintainance_1")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_1 is wrong.", 0,
                cqQuery.getCqResultKeysSize());
          }
        }
      }
    });

    // Update 1.
    cqDUnitTest.createValues(server, cqDUnitTest.regions[0], 10);
    cqDUnitTest.waitForCreated(client, "testKeyMaintainance_0", CqQueryDUnitTest.KEY + 10);

    // Entry/check is made into the CQs cache hashset.
    // testKeyMaintainance_0 with 1 entry and testKeyMaintainance_1 with 1
    server.invoke(new CacheSerializableRunnable("LookForCachedEventKeysAfterUpdate1") {
      @Override
      public void run2() throws CacheException {
        CqService cqService = null;
        try {
          cqService = ((DefaultQueryService) getCache().getQueryService()).getCqService();
        } catch (Exception ex) {
          LogWriterUtils.getLogWriter().info("Failed to get the internal CqService.", ex);
          Assert.fail("Failed to get the internal CqService.", ex);
        }
        Collection<? extends InternalCqQuery> cqs = cqService.getAllCqs();
        for (InternalCqQuery cq : cqs) {
          ServerCQImpl cqQuery = (ServerCQImpl) cq;

          String serverCqName = cqQuery.getServerCqName();
          if (serverCqName.startsWith("testKeyMaintainance_0")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_0 is wrong.", 10,
                cqQuery.getCqResultKeysSize());
          } else if (serverCqName.startsWith("testKeyMaintainance_1")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_1 is wrong.", 5,
                cqQuery.getCqResultKeysSize());
          }
        }
      }
    });

    // Update.
    cqDUnitTest.createValues(server, cqDUnitTest.regions[0], 12);
    cqDUnitTest.waitForCreated(client, "testKeyMaintainance_0", CqQueryDUnitTest.KEY + 12);

    // Entry/check is made into the CQs cache hashset.
    // testKeyMaintainance_0 with 1 entry and testKeyMaintainance_1 with 1
    server.invoke(new CacheSerializableRunnable("LookForCachedEventKeysAfterUpdate2") {
      @Override
      public void run2() throws CacheException {
        CqService cqService = null;
        try {
          cqService = ((DefaultQueryService) getCache().getQueryService()).getCqService();
        } catch (Exception ex) {
          LogWriterUtils.getLogWriter().info("Failed to get the internal CqService.", ex);
          Assert.fail("Failed to get the internal CqService.", ex);
        }

        Collection<? extends InternalCqQuery> cqs = cqService.getAllCqs();
        for (InternalCqQuery cq : cqs) {
          ServerCQImpl cqQuery = (ServerCQImpl) cq;

          String serverCqName = cqQuery.getServerCqName();
          if (serverCqName.startsWith("testKeyMaintainance_0")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_0 is wrong.", 12,
                cqQuery.getCqResultKeysSize());
          } else if (serverCqName.startsWith("testKeyMaintainance_1")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_1 is wrong.", 6,
                cqQuery.getCqResultKeysSize());
          }
        }

      }
    });

    // Delete.
    cqDUnitTest.deleteValues(server, cqDUnitTest.regions[0], 6);
    cqDUnitTest.waitForDestroyed(client, "testKeyMaintainance_0", CqQueryDUnitTest.KEY + 6);

    // Entry/check is made into the CQs cache hashset.
    // testKeyMaintainance_0 with 1 entry and testKeyMaintainance_1 with 1
    server.invoke(new CacheSerializableRunnable("LookForCachedEventKeysAfterUpdate2") {
      @Override
      public void run2() throws CacheException {
        CqService cqService = null;
        try {
          cqService = ((DefaultQueryService) getCache().getQueryService()).getCqService();
        } catch (Exception ex) {
          LogWriterUtils.getLogWriter().info("Failed to get the internal CqService.", ex);
          Assert.fail("Failed to get the internal CqService.", ex);
        }
        Collection<? extends InternalCqQuery> cqs = cqService.getAllCqs();
        for (InternalCqQuery cq : cqs) {
          ServerCQImpl cqQuery = (ServerCQImpl) cq;

          String serverCqName = cqQuery.getServerCqName();
          if (serverCqName.startsWith("testKeyMaintainance_0")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_0 is wrong.", 6,
                cqQuery.getCqResultKeysSize());
          } else if (serverCqName.startsWith("testKeyMaintainance_1")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_1 is wrong.", 3,
                cqQuery.getCqResultKeysSize());
          }
        }
      }
    });

    // This should still needs to process the events so that Results are uptodate.
    cqDUnitTest.stopCQ(client, "testKeyMaintainance_1");
    cqDUnitTest.createValues(server, cqDUnitTest.regions[0], 12);

    server.invoke(new CacheSerializableRunnable("LookForCachedEventKeysAfterUpdate2") {
      @Override
      public void run2() throws CacheException {
        CqService cqService = null;
        try {
          cqService = ((DefaultQueryService) getCache().getQueryService()).getCqService();
        } catch (Exception ex) {
          LogWriterUtils.getLogWriter().info("Failed to get the internal CqService.", ex);
          Assert.fail("Failed to get the internal CqService.", ex);
        }

        Collection<? extends InternalCqQuery> cqs = cqService.getAllCqs();
        for (InternalCqQuery cq : cqs) {
          ServerCQImpl cqQuery = (ServerCQImpl) cq;
          String serverCqName = cqQuery.getServerCqName();
          if (serverCqName.startsWith("testKeyMaintainance_0")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_0 is wrong.", 12,
                cqQuery.getCqResultKeysSize());
          } else if (serverCqName.startsWith("testKeyMaintainance_1")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_1 is wrong.", 6,
                cqQuery.getCqResultKeysSize());
          }
        }

      }
    });

    // This should re-start the caching for this CQ.
    cqDUnitTest.executeCQ(client, "testKeyMaintainance_1", false, null);

    // This will remove the caching for this CQ.
    cqDUnitTest.closeCQ(client, "testKeyMaintainance_1");
    server.invoke(new CacheSerializableRunnable("LookForCachedEventKeysAfterUpdate2") {
      @Override
      public void run2() throws CacheException {
        CqService cqService = null;
        try {
          cqService = ((DefaultQueryService) getCache().getQueryService()).getCqService();
        } catch (Exception ex) {
          LogWriterUtils.getLogWriter().info("Failed to get the internal CqService.", ex);
          Assert.fail("Failed to get the internal CqService.", ex);
        }
        Collection<? extends InternalCqQuery> cqs = cqService.getAllCqs();
        for (InternalCqQuery cq : cqs) {
          ServerCQImpl cqQuery = (ServerCQImpl) cq;
          String serverCqName = cqQuery.getServerCqName();
          if (serverCqName.startsWith("testKeyMaintainance_0")) {
            assertEquals("The number of keys cached for cq testKeyMaintainance_0 is wrong.", 12,
                cqQuery.getCqResultKeysSize());
          } else if (serverCqName.startsWith("testKeyMaintainance_1")) {
            fail("The key maintainance should not be present for this CQ.");
          }
        }

      }
    });

    // Close.
    cqDUnitTest.closeClient(client);
    cqDUnitTest.closeServer(server);
  }
Test for maintaining keys for update optimization.
geode-cq/src/distributedTest/java/org/apache/geode/cache/query/cq/dunit/CqPerfUsingPoolDUnitTest.java