@Test
  public void testPutAllEventSequenceOnSerialGatewaySenderWithRR() {

    // create two distributed systems with each having a cache containing
    // a Replicated Region with one entry and concurrency checks enabled.

    // Site 1
    Integer lnPort = vm0.invoke(() -> WANTestBase.createFirstLocatorWithDSId(1));
    vm1.invoke(() -> WANTestBase.createCache(lnPort));
    Integer lnRecPort = vm1.invoke(WANTestBase::createReceiver);

    // Site 2
    Integer nyPort = vm2.invoke(() -> WANTestBase.createFirstRemoteLocator(2, lnPort));
    vm3.invoke(() -> WANTestBase.createCache(nyPort));
    Integer nyRecPort = vm3.invoke(WANTestBase::createReceiver);

    LogWriterUtils.getLogWriter().info("Created locators and receivers in 2 distributed systems");

    // Site 1
    vm1.invoke(() -> WANTestBase.createSender("ln1", 2, false, 10, 1, false, false, null, true));

    vm1.invoke(() -> WANTestBase.createReplicatedRegion("repRegion", "ln1", isOffHeap()));
    vm1.invoke(() -> WANTestBase.startSender("ln1"));
    vm1.invoke(() -> WANTestBase.waitForSenderRunningState("ln1"));

    // Site 2
    vm3.invoke(() -> WANTestBase.createSender("ny1", 1, false, 10, 1, false, false, null, true));

    vm3.invoke(() -> WANTestBase.createReplicatedRegion("repRegion", "ny1", isOffHeap()));
    vm3.invoke(() -> WANTestBase.startSender("ny1"));
    vm3.invoke(() -> WANTestBase.waitForSenderRunningState("ny1"));

    Wait.pause(2000);

    // Perform a put in vm1
    AsyncInvocation<Void> asynch1 =
        vm1.invokeAsync(new CacheSerializableRunnable("Putting an entry in ds1") {

          @Override
          public void run2() throws CacheException {
            assertNotNull(cache);
            // Test hook to make put wait after RE lock is released but before Gateway events are
            // sent.
            DistributedCacheOperation.SLOW_DISTRIBUTION_MS = 2000;

            Region region = cache.getRegion(SEPARATOR + "repRegion");
            Map testMap = new HashMap();
            testMap.put("testKey", "testValue1");
            region.putAll(testMap);

            assertEquals(1, region.size());
            assertEquals("testValue2", region.get("testKey"));
          }
        });

    // wait for vm1 to propagate put to vm3
    Wait.pause(1000);

    AsyncInvocation<Void> asynch2 =
        vm1.invokeAsync(new CacheSerializableRunnable("Putting an entry in ds1") {

          @Override
          public void run2() throws CacheException {
            assertNotNull(cache);
            Region region = cache.getRegion(SEPARATOR + "repRegion");

            while (!region.containsKey("testKey")) {
              Wait.pause(10);
            }
            // Test hook to make put wait after RE lock is released but before Gateway events are
            // sent.
            DistributedCacheOperation.SLOW_DISTRIBUTION_MS = 0;

            region.put("testKey", "testValue2");

            assertEquals(1, region.size());
            assertEquals("testValue2", region.get("testKey"));
          }
        });

    try {
      asynch1.join(5000);
      asynch2.join(5000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      vm1.invoke(new CacheSerializableRunnable("Reset Test Hook") {

        @Override
        public void run2() throws CacheException {
          DistributedCacheOperation.SLOW_DISTRIBUTION_MS = 0;
        }
      });
    }

    // Wait for all Gateway events be received by vm3.
    Wait.pause(1000);

    long putAllTimeStampVm1 = vm1
        .invoke(NewWANConcurrencyCheckForDestroyDUnitTest::getVersionTimestampAfterPutAllOp);

    long putAllTimeStampVm3 = vm3
        .invoke(NewWANConcurrencyCheckForDestroyDUnitTest::getVersionTimestampAfterPutAllOp);

    assertEquals(putAllTimeStampVm1, putAllTimeStampVm3);
  }
Test creates two sites and one Replicated Region on each with Serial GatewaySender on each.
Test checks for sequence of events being sent from site1 to site2 for PUTALL and PUT and
finally checks for final timestamp in version for RegionEntry with key "testKey". If timestamp
on both site is same that means events were transferred in correct sequence.
geode-wan/src/distributedTest/java/org/apache/geode/internal/cache/wan/misc/NewWANConcurrencyCheckForDestroyDUnitTest.java