@Test
  public void testReadFileToByteBuffer() throws IOException {
    File file = File.createTempFile("test", "1");
    file.deleteOnExit();
    FileChannel fileChannel = Utils.openChannel(file, false);
    byte[] referenceBytes = new byte[20];
    new Random().nextBytes(referenceBytes);
    FileUtils.writeByteArrayToFile(file, referenceBytes);

    // fill up fresh byteBuffer
    ByteBuffer buffer = ByteBuffer.allocate(20);
    Utils.readFileToByteBuffer(fileChannel, 0, buffer);
    assertArrayEquals("Data mismatch", referenceBytes, buffer.array());

    // write to byteBuffer based on buffer remaining
    buffer.limit(10);
    buffer.position(0);
    assertEquals("buffer remaining should be 10", 10, buffer.remaining());
    Utils.readFileToByteBuffer(fileChannel, 10, buffer);
    assertEquals("buffer remaining should be 0", 0, buffer.remaining());
    for (int i = 0; i < 10; i++) {
      assertEquals("First 10 bytes in buffer should match last 10 bytes in file", buffer.array()[i],
          referenceBytes[i + 10]);
    }

    // byteBuffer.remaining() + starting offset > file size, exception is expected.
    buffer.clear();
    assertEquals("buffer remaining should be 20", 20, buffer.remaining());
    try {
      Utils.readFileToByteBuffer(fileChannel, 1, buffer);
      fail("Should fail");
    } catch (IOException e) {
    }

    // starting offset exceeds file size, exception is expected.
    buffer.clear();
    assertEquals("buffer remaining should be 20", 20, buffer.remaining());
    try {
      Utils.readFileToByteBuffer(fileChannel, 21, buffer);
      fail("Should fail");
    } catch (IOException e) {
    }
  }
Return the internal byte array of the given {@link ByteBuffer}. It only works when the {@link ByteBuffer} is not
a direct {@link ByteBuffer}.
@param buffer The {@link ByteBuffer}.
@return The internal byte array.
@throws Exception Any unexpected error.
ambry-utils/src/test/java/com/github/ambry/utils/UtilsTest.java