public void testGet() throws IOException {
   int length = randomIntBetween(1, PAGE_SIZE * 3);
   BytesReference pbr = newBytesReference(length);
   int sliceOffset = randomIntBetween(0, length / 2);
   int sliceLength = Math.max(1, length - sliceOffset - 1);
   BytesReference slice = pbr.slice(sliceOffset, sliceLength);
   assertEquals(pbr.get(sliceOffset), slice.get(0));
   assertEquals(pbr.get(sliceOffset + sliceLength - 1), slice.get(sliceLength - 1));
 }
  public void testStreamInput() throws IOException {
    int length = randomIntBetween(10, scaledRandomIntBetween(PAGE_SIZE * 2, PAGE_SIZE * 20));
    BytesReference pbr = newBytesReference(length);
    StreamInput si = pbr.streamInput();
    assertNotNull(si);

    // read single bytes one by one
    assertEquals(pbr.get(0), si.readByte());
    assertEquals(pbr.get(1), si.readByte());
    assertEquals(pbr.get(2), si.readByte());

    // reset the stream for bulk reading
    si.reset();

    // buffer for bulk reads
    byte[] origBuf = new byte[length];
    random().nextBytes(origBuf);
    byte[] targetBuf = Arrays.copyOf(origBuf, origBuf.length);

    // bulk-read 0 bytes: must not modify buffer
    si.readBytes(targetBuf, 0, 0);
    assertEquals(origBuf[0], targetBuf[0]);
    si.reset();

    // read a few few bytes as ints
    int bytesToRead = randomIntBetween(1, length / 2);
    for (int i = 0; i < bytesToRead; i++) {
      int b = si.read();
      assertEquals(pbr.get(i) & 0xff, b);
    }
    si.reset();

    // bulk-read all
    si.readFully(targetBuf);
    assertArrayEquals(pbr.toBytes(), targetBuf);

    // continuing to read should now fail with EOFException
    try {
      si.readByte();
      fail("expected EOF");
    } catch (EOFException | IndexOutOfBoundsException eof) {
      // yay
    }

    // try to read more than the stream contains
    si.reset();
    expectThrows(IndexOutOfBoundsException.class, () -> si.readBytes(targetBuf, 0, length * 2));
  }
  public void testStreamInputBulkReadWithOffset() throws IOException {
    final int length = randomIntBetween(10, scaledRandomIntBetween(PAGE_SIZE * 2, PAGE_SIZE * 20));
    BytesReference pbr = newBytesReference(length);
    StreamInput si = pbr.streamInput();
    assertNotNull(si);

    // read a bunch of single bytes one by one
    int offset = randomIntBetween(1, length / 2);
    for (int i = 0; i < offset; i++) {
      assertEquals(si.available(), length - i);
      assertEquals(pbr.get(i), si.readByte());
    }

    // now do NOT reset the stream - keep the stream's offset!

    // buffer to compare remaining bytes against bulk read
    byte[] pbrBytesWithOffset = Arrays.copyOfRange(pbr.toBytes(), offset, length);
    // randomized target buffer to ensure no stale slots
    byte[] targetBytes = new byte[pbrBytesWithOffset.length];
    random().nextBytes(targetBytes);

    // bulk-read all
    si.readFully(targetBytes);
    assertArrayEquals(pbrBytesWithOffset, targetBytes);
    assertEquals(si.available(), 0);
  }
 private int findNextMarker(byte marker, int from, BytesReference data, int length) {
   for (int i = from; i < length; i++) {
     if (data.get(i) == marker) {
       return i;
     }
   }
   return -1;
 }
  public void testSliceStreamInput() throws IOException {
    int length = randomIntBetween(10, scaledRandomIntBetween(PAGE_SIZE * 2, PAGE_SIZE * 20));
    BytesReference pbr = newBytesReference(length);

    // test stream input over slice (upper half of original)
    int sliceOffset = randomIntBetween(1, length / 2);
    int sliceLength = length - sliceOffset;
    BytesReference slice = pbr.slice(sliceOffset, sliceLength);
    StreamInput sliceInput = slice.streamInput();
    assertEquals(sliceInput.available(), sliceLength);

    // single reads
    assertEquals(slice.get(0), sliceInput.readByte());
    assertEquals(slice.get(1), sliceInput.readByte());
    assertEquals(slice.get(2), sliceInput.readByte());
    assertEquals(sliceInput.available(), sliceLength - 3);

    // reset the slice stream for bulk reading
    sliceInput.reset();
    assertEquals(sliceInput.available(), sliceLength);

    // bulk read
    byte[] sliceBytes = new byte[sliceLength];
    sliceInput.readFully(sliceBytes);
    assertEquals(sliceInput.available(), 0);

    // compare slice content with upper half of original
    byte[] pbrSliceBytes = Arrays.copyOfRange(pbr.toBytes(), sliceOffset, length);
    assertArrayEquals(pbrSliceBytes, sliceBytes);

    // compare slice bytes with bytes read from slice via streamInput :D
    byte[] sliceToBytes = slice.toBytes();
    assertEquals(sliceBytes.length, sliceToBytes.length);
    assertArrayEquals(sliceBytes, sliceToBytes);

    sliceInput.reset();
    assertEquals(sliceInput.available(), sliceLength);
    byte[] buffer = new byte[sliceLength + scaledRandomIntBetween(1, 100)];
    int offset = scaledRandomIntBetween(0, Math.max(1, buffer.length - sliceLength - 1));
    int read = sliceInput.read(buffer, offset, sliceLength / 2);
    assertEquals(sliceInput.available(), sliceLength - read);
    sliceInput.read(buffer, offset + read, sliceLength - read);
    assertArrayEquals(sliceBytes, Arrays.copyOfRange(buffer, offset, offset + sliceLength));
    assertEquals(sliceInput.available(), 0);
  }