private void verifyWritesSeen(final WAL log, final SampleRegionWALCoprocessor cp,
    final boolean seesLegacy) throws Exception {
    RegionInfo hri = createBasicHRegionInfo(Bytes.toString(TEST_TABLE));
    TableDescriptor htd = createBasic3FamilyHTD(Bytes.toString(TEST_TABLE));
    NavigableMap<byte[], Integer> scopes = new TreeMap<>(Bytes.BYTES_COMPARATOR);
    for (byte[] fam : htd.getColumnFamilyNames()) {
      scopes.put(fam, 0);
    }
    Path basedir = new Path(this.hbaseRootDir, Bytes.toString(TEST_TABLE));
    deleteDir(basedir);
    fs.mkdirs(new Path(basedir, hri.getEncodedName()));

    // TEST_FAMILY[0] shall be removed from WALEdit.
    // TEST_FAMILY[1] value shall be changed.
    // TEST_FAMILY[2] shall be added to WALEdit, although it's not in the put.
    cp.setTestValues(TEST_TABLE, TEST_ROW, TEST_FAMILY[0], TEST_QUALIFIER[0], TEST_FAMILY[1],
      TEST_QUALIFIER[1], TEST_FAMILY[2], TEST_QUALIFIER[2]);

    assertFalse(cp.isPreWALWriteCalled());
    assertFalse(cp.isPostWALWriteCalled());

    // TEST_FAMILY[2] is not in the put, however it shall be added by the tested
    // coprocessor.
    // Use a Put to create familyMap.
    Put p = creatPutWith2Families(TEST_ROW);

    Map<byte[], List<Cell>> familyMap = p.getFamilyCellMap();
    WALEdit edit = new WALEdit();
    edit.add(familyMap);

    boolean foundFamily0 = false;
    boolean foundFamily2 = false;
    boolean modifiedFamily1 = false;

    List<Cell> cells = edit.getCells();

    for (Cell cell : cells) {
      if (Arrays.equals(CellUtil.cloneFamily(cell), TEST_FAMILY[0])) {
        foundFamily0 = true;
      }
      if (Arrays.equals(CellUtil.cloneFamily(cell), TEST_FAMILY[2])) {
        foundFamily2 = true;
      }
      if (Arrays.equals(CellUtil.cloneFamily(cell), TEST_FAMILY[1])) {
        if (!Arrays.equals(CellUtil.cloneValue(cell), TEST_VALUE[1])) {
          modifiedFamily1 = true;
        }
      }
    }
    assertTrue(foundFamily0);
    assertFalse(foundFamily2);
    assertFalse(modifiedFamily1);

    // it's where WAL write cp should occur.
    long now = EnvironmentEdgeManager.currentTime();
    // we use HLogKey here instead of WALKeyImpl directly to support legacy coprocessors.
    long txid = log.appendData(hri, new WALKeyImpl(hri.getEncodedNameAsBytes(), hri.getTable(), now,
      new MultiVersionConcurrencyControl(), scopes), edit);
    log.sync(txid);

    // the edit shall have been change now by the coprocessor.
    foundFamily0 = false;
    foundFamily2 = false;
    modifiedFamily1 = false;
    for (Cell cell : cells) {
      if (Arrays.equals(CellUtil.cloneFamily(cell), TEST_FAMILY[0])) {
        foundFamily0 = true;
      }
      if (Arrays.equals(CellUtil.cloneFamily(cell), TEST_FAMILY[2])) {
        foundFamily2 = true;
      }
      if (Arrays.equals(CellUtil.cloneFamily(cell), TEST_FAMILY[1])) {
        if (!Arrays.equals(CellUtil.cloneValue(cell), TEST_VALUE[1])) {
          modifiedFamily1 = true;
        }
      }
    }
    assertFalse(foundFamily0);
    assertTrue(foundFamily2);
    assertTrue(modifiedFamily1);

    assertTrue(cp.isPreWALWriteCalled());
    assertTrue(cp.isPostWALWriteCalled());
  }
Test WAL write behavior with WALObserver. The coprocessor monitors a WALEdit written to WAL,
and ignore, modify, and add KeyValue's for the WALEdit.
hbase-server/src/test/java/org/apache/hadoop/hbase/coprocessor/TestWALObserver.java