private void doTestClientGetsInvalidEntry(final String regionName, final boolean usePR,
      boolean useTX) throws Exception {
    VM vm1 = Host.getHost(0).getVM(1);
    VM vm2 = Host.getHost(0).getVM(2);

    // here are the keys that will be used to validate behavior. Keys must be
    // colocated if using both a partitioned region in the server and transactions
    // in the client. All of these keys hash to bucket 0 in a two-bucket PR
    // except Object11 and IDoNotExist1
    final String notAffectedKey = "Object1";
    final String nonexistentKey = (usePR && useTX) ? "IDoNotExist2" : "IDoNotExist1";
    final String key1 = "Object10";
    final String key2 = (usePR && useTX) ? "Object12" : "Object11";

    SerializableCallableIF createServer = getCreateServerCallable(regionName, usePR);
    int serverPort = (Integer) vm1.invoke(createServer);
    vm2.invoke(createServer);
    vm1.invoke(new SerializableRunnable("populate server and create invalid entry") {
      @Override
      public void run() {
        Region myRegion = getCache().getRegion(regionName);
        for (int i = 1; i <= 20; i++) {
          myRegion.put("Object" + i, "Value" + i);
        }
        myRegion.invalidate(key1);
        myRegion.invalidate(key2);
      }
    });
    org.apache.geode.test.dunit.LogWriterUtils.getLogWriter().info("creating client cache");
    ClientCache c = new ClientCacheFactory().addPoolServer("localhost", serverPort)
        .set(LOG_LEVEL, LogWriterUtils.getDUnitLogLevel()).create();
    Region myRegion =
        c.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY).create(regionName);
    if (useTX) {
      c.getCacheTransactionManager().begin();
    }

    // get of a valid entry should work
    assertNotNull(myRegion.get(notAffectedKey));

    // get of an invalid entry should return null and create the entry in an invalid state
    org.apache.geode.test.dunit.LogWriterUtils.getLogWriter()
        .info("getting " + key1 + " - should reach this cache and be INVALID");
    assertNull(myRegion.get(key1));
    assertTrue(myRegion.containsKey(key1));

    // since this might be a PR we also check the next key to force PR Get messaging
    assertNull(myRegion.get(key2));
    assertTrue(myRegion.containsKey(key2));

    // now try a key that doesn't exist anywhere
    assertNull(myRegion.get(nonexistentKey));
    assertFalse(myRegion.containsKey(nonexistentKey));

    if (useTX) {
      c.getCacheTransactionManager().commit();

      // test that the commit correctly created the entries in the region
      assertNotNull(myRegion.get(notAffectedKey));
      assertNull(myRegion.get(key1));
      assertTrue(myRegion.containsKey(key1));
      assertNull(myRegion.get(key2));
      assertTrue(myRegion.containsKey(key2));
    }

    myRegion.localDestroy(notAffectedKey);
    myRegion.localDestroy(key1);
    myRegion.localDestroy(key2);

    if (useTX) {
      c.getCacheTransactionManager().begin();
    }

    // check that getAll returns invalidated entries
    List keys = new LinkedList();
    keys.add(notAffectedKey);
    keys.add(key1);
    keys.add(key2);
    Map result = myRegion.getAll(keys);

    assertNotNull(result.get(notAffectedKey));
    assertNull(result.get(key1));
    assertNull(result.get(key2));
    assertTrue(result.containsKey(key1));
    assertTrue(result.containsKey(key2));
    assertTrue(myRegion.containsKey(key1));
    assertTrue(myRegion.containsKey(key2));

    if (useTX) {
      c.getCacheTransactionManager().commit();
      // test that the commit correctly created the entries in the region
      assertNotNull(myRegion.get(notAffectedKey));
      assertNull(myRegion.get(key1));
      assertTrue(myRegion.containsKey(key1));
      assertNull(myRegion.get(key2));
      assertTrue(myRegion.containsKey(key2));
    }

    // test that a listener is not invoked when there is already an invalidated
    // entry in the client cache
    UpdateListener listener = new UpdateListener();
    listener.log = org.apache.geode.test.dunit.LogWriterUtils.getLogWriter();
    myRegion.getAttributesMutator().addCacheListener(listener);
    myRegion.get(key1);
    assertEquals("expected no cache listener invocations", 0, listener.updateCount,
        listener.updateCount);

    myRegion.localDestroy(notAffectedKey);
    myRegion.getAll(keys);
    assertTrue("expected to find " + notAffectedKey, myRegion.containsKey(notAffectedKey));
    assertEquals("expected only one listener invocation for " + notAffectedKey, 1,
        listener.updateCount);
  }
Bug #43407 - when a client does a get(k) and the entry is invalid in the server we want the
client to end up with an entry that is invalid.
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/ClientServerInvalidAndDestroyedEntryDUnitTest.java