@Test
  public void testScanWithDoubleFlush() throws IOException {
    Configuration conf = HBaseConfiguration.create();
    // Initialize region
    MyStore myStore = initMyStore(name.getMethodName(), conf, new MyStoreHook() {
      @Override
      public void getScanners(MyStore store) throws IOException {
        final long tmpId = id++;
        ExecutorService s = Executors.newSingleThreadExecutor();
        s.execute(() -> {
          try {
            // flush the store before storescanner updates the scanners from store.
            // The current data will be flushed into files, and the memstore will
            // be clear.
            // -- phase (4/4)
            flushStore(store, tmpId);
          } catch (IOException ex) {
            throw new RuntimeException(ex);
          }
        });
        s.shutdown();
        try {
          // wait for the flush, the thread will be blocked in HStore#notifyChangedReadersObservers.
          s.awaitTermination(3, TimeUnit.SECONDS);
        } catch (InterruptedException ex) {
        }
      }
    });
    byte[] oldValue = Bytes.toBytes("oldValue");
    byte[] currentValue = Bytes.toBytes("currentValue");
    MemStoreSizing memStoreSizing = new NonThreadSafeMemStoreSizing();
    long ts = EnvironmentEdgeManager.currentTime();
    long seqId = 100;
    // older data whihc shouldn't be "seen" by client
    myStore.add(createCell(qf1, ts, seqId, oldValue), memStoreSizing);
    myStore.add(createCell(qf2, ts, seqId, oldValue), memStoreSizing);
    myStore.add(createCell(qf3, ts, seqId, oldValue), memStoreSizing);
    long snapshotId = id++;
    // push older data into snapshot -- phase (1/4)
    StoreFlushContext storeFlushCtx =
      store.createFlushContext(snapshotId, FlushLifeCycleTracker.DUMMY);
    storeFlushCtx.prepare();

    // insert current data into active -- phase (2/4)
    myStore.add(createCell(qf1, ts + 1, seqId + 1, currentValue), memStoreSizing);
    myStore.add(createCell(qf2, ts + 1, seqId + 1, currentValue), memStoreSizing);
    myStore.add(createCell(qf3, ts + 1, seqId + 1, currentValue), memStoreSizing);
    TreeSet<byte[]> quals = new TreeSet<>(Bytes.BYTES_COMPARATOR);
    quals.add(qf1);
    quals.add(qf2);
    quals.add(qf3);
    try (InternalScanner scanner =
      (InternalScanner) myStore.getScanner(new Scan(new Get(row)), quals, seqId + 1)) {
      // complete the flush -- phase (3/4)
      storeFlushCtx.flushCache(Mockito.mock(MonitoredTask.class));
      storeFlushCtx.commit(Mockito.mock(MonitoredTask.class));

      List<Cell> results = new ArrayList<>();
      scanner.next(results);
      assertEquals(3, results.size());
      for (Cell c : results) {
        byte[] actualValue = CellUtil.cloneValue(c);
        assertTrue("expected:" + Bytes.toStringBinary(currentValue) + ", actual:"
          + Bytes.toStringBinary(actualValue), Bytes.equals(actualValue, currentValue));
      }
    }
  }
Test for HBASE-3492 - Test split on empty colfam (no store files).
@throws IOException When the IO operations fail.
hbase-server/src/test/java/org/apache/hadoop/hbase/regionserver/TestHStore.java