@Test
public void testDiscardReadBytes() {

    buffer.writerIndex(0);
    for (int i = 0; i < buffer.capacity(); i += 4) {
        buffer.writeInt(i);
    }
    ByteBuf copy = copiedBuffer(buffer);
    // Make sure there's no effect if called when readerIndex is 0.
    buffer.readerIndex(CAPACITY / 4);
    buffer.markReaderIndex();
    buffer.writerIndex(CAPACITY / 3);
    buffer.markWriterIndex();
    buffer.readerIndex(0);
    buffer.writerIndex(CAPACITY / 2);
    buffer.discardReadBytes();
    assertEquals(0, buffer.readerIndex());
    assertEquals(CAPACITY / 2, buffer.writerIndex());
    assertEquals(copy.slice(0, CAPACITY / 2), buffer.slice(0, CAPACITY / 2));
    buffer.resetReaderIndex();
    assertEquals(CAPACITY / 4, buffer.readerIndex());
    buffer.resetWriterIndex();
    assertEquals(CAPACITY / 3, buffer.writerIndex());
    // Make sure bytes after writerIndex is not copied.
    buffer.readerIndex(1);
    buffer.writerIndex(CAPACITY / 2);
    buffer.discardReadBytes();
    assertEquals(0, buffer.readerIndex());
    assertEquals(CAPACITY / 2 - 1, buffer.writerIndex());
    assertEquals(copy.slice(1, CAPACITY / 2 - 1), buffer.slice(0, CAPACITY / 2 - 1));
    if (discardReadBytesDoesNotMoveWritableBytes()) {
        // If writable bytes were copied, the test should fail to avoid unnecessary memory bandwidth consumption.
        assertFalse(copy.slice(CAPACITY / 2, CAPACITY / 2).equals(buffer.slice(CAPACITY / 2 - 1, CAPACITY / 2)));
    } else {
        assertEquals(copy.slice(CAPACITY / 2, CAPACITY / 2), buffer.slice(CAPACITY / 2 - 1, CAPACITY / 2));
    }
    // Marks also should be relocated.
    buffer.resetReaderIndex();
    assertEquals(CAPACITY / 4 - 1, buffer.readerIndex());
    buffer.resetWriterIndex();
    assertEquals(CAPACITY / 3 - 1, buffer.writerIndex());
    copy.release();
}