@Test
  public void testBlockMultiLimits() throws Exception {
    final TableName tableName = TableName.valueOf(name.getMethodName());
    TEST_UTIL.getAdmin().createTable(
      TableDescriptorBuilder.newBuilder(tableName).setColumnFamily(ColumnFamilyDescriptorBuilder
        .newBuilder(FAMILY).setDataBlockEncoding(DataBlockEncoding.FAST_DIFF).build()).build());
    Table t = TEST_UTIL.getConnection().getTable(tableName);

    final HRegionServer regionServer = TEST_UTIL.getHBaseCluster().getRegionServer(0);
    RpcServerInterface rpcServer = regionServer.getRpcServer();
    BaseSource s = rpcServer.getMetrics().getMetricsSource();
    long startingExceptions = METRICS_ASSERT.getCounter("exceptions", s);
    long startingMultiExceptions = METRICS_ASSERT.getCounter("exceptions.multiResponseTooLarge", s);

    byte[] row = Bytes.toBytes("TEST");
    byte[][] cols = new byte[][] { Bytes.toBytes("0"), // Get this
      Bytes.toBytes("1"), // Buffer
      Bytes.toBytes("2"), // Buffer
      Bytes.toBytes("3"), // Get This
      Bytes.toBytes("4"), // Buffer
      Bytes.toBytes("5"), // Buffer
      Bytes.toBytes("6"), // Buffer
      Bytes.toBytes("7"), // Get This
      Bytes.toBytes("8"), // Buffer
      Bytes.toBytes("9"), // Buffer
    };

    // Set the value size so that one result will be less than the MAX_SIZE
    // however the block being reference will be larger than MAX_SIZE.
    // This should cause the regionserver to try and send a result immediately.
    byte[] value = new byte[1];
    Bytes.random(value);

    for (int i = 0; i < cols.length; i++) {
      if (i == 6) {
        // do a flush here so we end up with 2 blocks, 55 and 45 bytes
        flush(regionServer, tableName);
      }
      byte[] col = cols[i];
      Put p = new Put(row);
      p.add(CellBuilderFactory.create(CellBuilderType.SHALLOW_COPY).setRow(row).setFamily(FAMILY)
        .setQualifier(col).setTimestamp(p.getTimestamp()).setType(Cell.Type.Put).setValue(value)
        .build());
      t.put(p);
    }

    // Make sure that a flush happens
    flush(regionServer, tableName);

    List<Get> gets = new ArrayList<>(4);
    // This get returns nothing since the filter doesn't match. Filtered cells still retain
    // blocks, and this is a full row scan of both blocks. This equals 100 bytes so we should
    // throw a multiResponseTooLarge after this get if we are counting filtered cells correctly.
    Get g0 = new Get(row).addFamily(FAMILY).setFilter(
      new QualifierFilter(CompareOperator.EQUAL, new BinaryComparator(Bytes.toBytes("sdf"))));
    gets.add(g0);

    // g1 and g2 each count the first 55 byte block, so we end up with block size of 110
    // after g2 and throw a multiResponseTooLarge before g3
    Get g1 = new Get(row);
    g1.addColumn(FAMILY, cols[0]);
    gets.add(g1);

    Get g2 = new Get(row);
    g2.addColumn(FAMILY, cols[3]);
    gets.add(g2);

    Get g3 = new Get(row);
    g3.addColumn(FAMILY, cols[7]);
    gets.add(g3);

    Result[] results = t.get(gets);
    assertEquals(4, results.length);
    // Expect 2 exceptions (thus 3 rpcs) -- one for g0, then another for g1 + g2, final rpc for g3.
    // If we tracked lastBlock we could squeeze g3 into the second rpc because g2 would be "free"
    // since it's in the same block as g1.
    METRICS_ASSERT.assertCounterGt("exceptions", startingExceptions + 1, s);
    METRICS_ASSERT.assertCounterGt("exceptions.multiResponseTooLarge", startingMultiExceptions + 1,
      s);
  }
This test sets the multi size WAAAAAY low and then checks to make sure that gets will still make
progress.
hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestMultiRespectsLimits.java