private void doReplacePutsKeyInLocalClientCacheWork(final String regionName) {
    Host host = Host.getHost(0);
    VM server = host.getVM(0);
    VM client = host.getVM(2);
    int port1 = createRegionsAndStartServer(server);

    createClientRegion(client, port1, false, -1);
    server.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        final Region r = getCache().getRegion(regionName);
        assertNull(r.putIfAbsent("key0", "value"));
        assertTrue(r.containsKey("key0"));
        assertNull(r.putIfAbsent("key2", "value2"));
        assertTrue(r.containsKey("key2"));
        return null;
      }
    });
    client.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        final Region r = getCache().getRegion(regionName);
        assertEquals("value", r.replace("key0", "newValue"));
        assertTrue(r.containsKeyOnServer("key0"));
        assertTrue(r.containsKey("key0"));
        assertTrue(r.containsValueForKey("key0"));

        assertFalse(r.replace("key2", "DontReplace", "newValue"));
        assertTrue(r.replace("key2", "value2", "newValu2"));
        assertTrue(r.containsKeyOnServer("key2"));
        assertTrue(r.containsKey("key2"));
        assertTrue(r.containsValueForKey("key2"));
        return null;
      }
    });
    // bug #42221 - replace does not put entry on client when server has invalid value
    client.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getCache().getRegion(regionName);
        final String key = "bug42221";
        r.putIfAbsent(key, null);
        assertTrue(r.containsKey(key));
        Object result = r.replace(key, "not null");
        assertEquals(null, result);
        assertTrue(r.containsKey(key));
        assertEquals(r.get(key), "not null");
        r.remove(key); // cleanup
        return null;
      }
    });
    // bug #42242 - remove(K,null) doesn't work
    client.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getCache().getRegion(regionName);
        final String key = "bug42242";
        r.putIfAbsent(key, null);
        assertTrue(r.containsKey(key));
        assertTrue(r.containsKeyOnServer(key));
        boolean result = r.remove(key, null);
        assertTrue(result);
        assertFalse(r.containsKey(key));
        assertFalse(r.containsKeyOnServer(key));
        return null;
      }
    });
    // bug #42242b - second scenario with a replace(K,V,V) that didn't work
    client.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getCache().getRegion(regionName);
        final String key = "bug42242b";
        r.putIfAbsent(key, null);
        assertTrue(r.containsKey(key));
        assertTrue(r.containsKeyOnServer(key));
        boolean result = r.replace(key, null, "new value");
        assertTrue(result);
        result = r.remove(key, "new value");
        assertTrue(result);
        assertFalse(r.containsKey(key));
        assertFalse(r.containsKeyOnServer(key));
        return null;
      }
    });
    // bug #42242c - remove does not work for entry that's on the server but not on the client
    final String key = "bug42242c";
    client.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getCache().getRegion(regionName);
        r.registerInterest("ALL_KEYS");
        return null;
      }
    });
    server.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        Region r = getCache().getRegion(regionName);
        r.putIfAbsent(key, null);
        assertTrue(r.containsKey(key));
        return null;
      }
    });
    client.invoke(new SerializableCallable() {
      @Override
      public Object call() throws Exception {
        final Region r = getCache().getRegion(regionName);
        WaitCriterion w = new WaitCriterion() {
          @Override
          public String description() {
            return "waiting for server operation to reach client";
          }

          @Override
          public boolean done() {
            return r.containsKey(key);
          }
        };
        GeodeAwaitility.await().untilAsserted(w);
        assertTrue(r.containsKeyOnServer(key));
        boolean result = r.remove(key, null);
        // if (!result) {
        // ((LocalRegion)r).dumpBackingMap();
        // }
        assertTrue(result);
        assertFalse(r.containsKey(key));
        assertFalse(r.containsKeyOnServer(key));
        return null;
      }
    });
  }
Partitioned Region test for bug #42195: putIfAbsent from client does not put old value in local
cache
geode-core/src/distributedTest/java/org/apache/geode/internal/cache/ConcurrentMapOpsDUnitTest.java