@SuppressWarnings({"unchecked", "rawtypes"})
  @Test
  public void testRegionVersionVectors() throws Exception {
    // this is just a quick set of unit tests for basic RVV functionality

    final String local = getIPLiteral();
    InternalDistributedMember server1 = new InternalDistributedMember(local, 101);
    InternalDistributedMember server2 = new InternalDistributedMember(local, 102);
    InternalDistributedMember server3 = new InternalDistributedMember(local, 103);
    InternalDistributedMember server4 = new InternalDistributedMember(local, 104);

    RegionVersionVector rv1 = null;

    // (a) Test that an exception is mended when the versions that are missing are
    // added
    rv1 = new VMRegionVersionVector(server1);
    rv1.recordVersion(server2, 1);
    rv1.recordVersion(server2, 5);
    rv1.recordVersion(server2, 8);
    System.out.println("for test (a) formed this RVV: " + rv1.fullToString());
    // there should now be two exceptions: 1-5 and 5-8
    assertEquals(8, rv1.getVersionForMember(server2));
    assertEquals(2, rv1.getExceptionCount(server2));
    rv1.recordVersion(server2, 3);
    System.out.println("for test (a) RVV is now: " + rv1.fullToString());
    assertEquals(8, rv1.getVersionForMember(server2));
    assertEquals(2, rv1.getExceptionCount(server2));
    rv1.recordVersion(server2, 4);
    rv1.recordVersion(server2, 2);
    System.out.println("for test (a) RVV is now: " + rv1.fullToString());
    assertEquals(1, rv1.getExceptionCount(server2));
    rv1.recordVersion(server2, 6);
    rv1.recordVersion(server2, 7);
    System.out.println("for test (a) RVV is now: " + rv1.fullToString());
    assertEquals(0, rv1.getExceptionCount(server2));

    // (b) Test the contains() operation
    rv1 = new VMRegionVersionVector(server1);
    rv1.recordVersion(server2, 1);
    rv1.recordVersion(server2, 5);
    rv1.recordVersion(server2, 8);
    rv1.recordVersion(server2, 10);
    System.out.println("for test (b) formed this RVV: " + rv1.fullToString());
    assertTrue(rv1.contains(server2, 1));
    assertTrue(rv1.contains(server2, 5));
    assertTrue(rv1.contains(server2, 8));
    assertTrue(rv1.contains(server2, 10));
    assertFalse(rv1.contains(server2, 2));
    assertFalse(rv1.contains(server2, 3));
    assertFalse(rv1.contains(server2, 4));
    assertFalse(rv1.contains(server2, 9));
    assertFalse(rv1.contains(server2, 11));
    rv1.recordVersion(server2, 3);
    System.out.println("for test (b) RVV is now: " + rv1.fullToString());
    assertTrue(rv1.contains(server2, 3));
    rv1.recordVersion(server2, 2);
    System.out.println("for test (b) RVV is now: " + rv1.fullToString());
    assertTrue(rv1.contains(server2, 2));
    assertTrue(rv1.contains(server2, 3));
    rv1.recordVersion(server2, 4);
    System.out.println("for test (b) RVV is now: " + rv1.fullToString());
    assertTrue(rv1.contains(server2, 1));
    assertTrue(rv1.contains(server2, 2));
    assertTrue(rv1.contains(server2, 3));
    assertTrue(rv1.contains(server2, 4));
    assertTrue(rv1.contains(server2, 5));
    rv1.recordVersion(server2, 11);
    System.out.println("for test (b) RVV is now: " + rv1.fullToString());
    assertTrue(rv1.contains(server2, 11));
    assertTrue(rv1.contains(server2, 10));
    System.out.println("for test (b) RVV is now: " + rv1.fullToString());
    rv1.recordVersion(server2, 6);
    assertTrue(rv1.contains(server2, 2));
    assertTrue(rv1.contains(server2, 5));
    assertTrue(rv1.contains(server2, 6));
    assertFalse(rv1.contains(server2, 7));
    assertTrue(rv1.contains(server2, 8));
    rv1.recordVersion(server2, 7);
    System.out.println("for test (b) RVV is now: " + rv1.fullToString());
    assertTrue(rv1.contains(server2, 7));
    rv1.recordVersion(server2, 9);
    System.out.println("for test (b) RVV is now: " + rv1.fullToString());
    assertTrue(rv1.contains(server2, 9));
    assertTrue(rv1.getExceptionCount(server2) == 0);
    assertTrue(rv1.contains(server2, 8));

    // Test RVV comparisons for GII Delta
    rv1 = new VMRegionVersionVector(server1);
    rv1.recordVersion(server2, 1);
    rv1.recordVersion(server2, 4);
    rv1.recordVersion(server2, 8);
    rv1.recordVersion(server2, 9);
    rv1.recordVersion(server2, 10);
    rv1.recordVersion(server2, 11);
    rv1.recordVersion(server2, 12);

    rv1.recordVersion(server3, 2);
    rv1.recordVersion(server3, 3);
    rv1.recordVersion(server3, 4);
    rv1.recordVersion(server3, 6);
    rv1.recordVersion(server3, 7);

    RegionVersionVector rv2 = rv1.getCloneForTransmission();
    System.out.println("rv1 is " + rv1.fullToString());
    System.out.println("rv2 is " + rv2.fullToString());
    assertFalse(rv1.isNewerThanOrCanFillExceptionsFor(rv2));
    assertFalse(rv2.isNewerThanOrCanFillExceptionsFor(rv1));

    rv1.recordVersion(server2, 6);
    assertTrue(rv1.isNewerThanOrCanFillExceptionsFor(rv2));
    rv2.recordVersion(server2, 6);
    assertFalse(rv1.isNewerThanOrCanFillExceptionsFor(rv2));

    // fill an exception gap
    rv1.recordVersion(server2, 5);
    assertTrue(rv1.isNewerThanOrCanFillExceptionsFor(rv2));
    rv2.recordVersion(server2, 5);
    assertFalse(rv1.isNewerThanOrCanFillExceptionsFor(rv2));
    rv1.recordVersion(server2, 7);
    assertTrue(rv1.isNewerThanOrCanFillExceptionsFor(rv2));
    rv2.recordVersion(server2, 7);
    assertFalse(rv1.isNewerThanOrCanFillExceptionsFor(rv2));

    // add a more recent revision
    rv1.recordVersion(server3, 8);
    assertTrue(rv1.isNewerThanOrCanFillExceptionsFor(rv2));
    rv2.recordVersion(server3, 8);
    assertFalse(rv1.isNewerThanOrCanFillExceptionsFor(rv2));

    // fill another exception gap
    rv1.recordVersion(server3, 5);
    assertTrue(rv1.isNewerThanOrCanFillExceptionsFor(rv2));
    rv2.recordVersion(server3, 5);
    assertFalse(rv1.isNewerThanOrCanFillExceptionsFor(rv2));

    // test that old members are removed from the vector
    InternalDistributedMember server5 = new InternalDistributedMember(local, 105);
    rv1 = new VMRegionVersionVector(server1);
    rv1.recordVersion(server2, 1);
    rv1.recordVersion(server3, 1);
    rv1.recordVersion(server4, 1);
    rv1.recordVersion(server5, 1);
    rv1.memberDeparted(null, server2, false);
    rv1.memberDeparted(null, server4, true);
    assertTrue(rv1.containsMember(server2));
    assertTrue(rv1.containsMember(server3));
    assertTrue(rv1.containsMember(server4));
    Set retain = new HashSet();
    retain.add(server2); // still have data from server2
    retain.add(server3); // still have data from server3
    // no data found from server4 in region
    retain.add(server5); // still have data from server5
    rv1.removeOldMembers(retain);
    assertFalse(rv1.containsMember(server4));

    rv1.memberDeparted(null, server3, false); // {server2, server3(departed), server5}

    // Now test that departed members are transferred with GII. We simulate
    // a new server, server6, doing a GII from server1

    InternalDistributedMember server6 = new InternalDistributedMember(local, 106);
    RegionVersionVector giiReceiverRVV = new VMRegionVersionVector(server6);
    // the gii request will cause server1 to clone its RVV and send it to server6
    rv2 = rv1.getCloneForTransmission();
    // serialize/deserialize to mimic sending the rvv in a message
    ByteArrayOutputStream baos = new ByteArrayOutputStream(1000);
    DataOutputStream out = new DataOutputStream(baos);
    DataSerializer.writeObject(rv2, out);
    ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    DataInputStream in = new DataInputStream(bais);
    RegionVersionVector transmittedVector = DataSerializer.readObject(in);
    // record the provider's rvv in the receiver of the image
    giiReceiverRVV.recordVersions(transmittedVector);
    // removedMembers in the receiver should hold {server4, server3}. Simulate
    // another member departure to kick out server4
    assertTrue(giiReceiverRVV.containsMember(server2));
    assertTrue(giiReceiverRVV.containsMember(server5));
    assertTrue(giiReceiverRVV.containsMember(server3));
    assertTrue(giiReceiverRVV.isDepartedMember(server3));

    // unit test for bit-set boundary. First boundary is 3/4 of bitset width,
    // which is the amount dumped to the exceptions list when the bitset becomes full
    rv1 = new VMRegionVersionVector(server1);
    long bitSetRollPoint = RegionVersionHolder.BIT_SET_WIDTH + 1;
    long boundary = RegionVersionHolder.BIT_SET_WIDTH * 3 / 4;
    for (long i = 1; i < boundary; i++) {
      rv1.recordVersion(server2, i);
      assertTrue(rv1.contains(server2, i));
    }
    assertFalse(rv1.contains(server2, boundary + 1));

    rv1.recordVersion(server2, bitSetRollPoint);
    rv1.recordVersion(server2, bitSetRollPoint + 1); // bitSet should be rolled at this point
    RegionVersionHolder h = (RegionVersionHolder) rv1.getMemberToVersion().get(server2);
    long versionBoundary = h.getBitSetVersionForTesting();
    assertEquals("expected holder bitset version to roll to this value", boundary - 1,
        versionBoundary);
    assertFalse(rv1.contains(server2, bitSetRollPoint - 1));
    assertTrue(rv1.contains(server2, bitSetRollPoint));
    assertTrue(rv1.contains(server2, bitSetRollPoint + 1));
    assertFalse(rv1.contains(server2, bitSetRollPoint + 2));

    assertTrue(rv1.contains(server2, boundary - 1));
    assertFalse(rv1.contains(server2, boundary));
    assertFalse(rv1.contains(server2, boundary + 1));

    // now test the merge
    System.out.println("testing merge for " + rv1.fullToString());
    assertEquals(1, rv1.getExceptionCount(server2)); // one exception from boundary-1 to
    // bitSetRollPoint
    assertFalse(rv1.contains(server2, bitSetRollPoint - 1));
    assertTrue(rv1.contains(server2, bitSetRollPoint));
    assertTrue(rv1.contains(server2, bitSetRollPoint + 1));
    assertFalse(rv1.contains(server2, bitSetRollPoint + 2));
  }
server1 will simulate doing a sync with another server for operations performed
by server2. server3 is another server in the cluster that we don't care about
servers have version source as dist store id
geode-core/src/test/java/org/apache/geode/internal/cache/versions/RegionVersionVectorTest.java