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);
  }
  public void testWriteStreamableList() throws IOException {
    final int size = randomIntBetween(0, 5);
    final List<TestStreamable> expected = new ArrayList<>(size);

    for (int i = 0; i < size; ++i) {
      expected.add(new TestStreamable(randomBoolean()));
    }

    final BytesStreamOutput out = new BytesStreamOutput();
    out.writeStreamableList(expected);

    final StreamInput in = StreamInput.wrap(BytesReference.toBytes(out.bytes()));

    final List<TestStreamable> loaded = in.readStreamableList(TestStreamable::new);

    assertThat(loaded, hasSize(expected.size()));

    for (int i = 0; i < expected.size(); ++i) {
      assertEquals(expected.get(i).value, loaded.get(i).value);
    }

    assertEquals(0, in.available());

    in.close();
    out.close();
  }
 public void testWriteableReaderReturnsWrongName() throws IOException {
   BytesStreamOutput out = new BytesStreamOutput();
   NamedWriteableRegistry namedWriteableRegistry =
       new NamedWriteableRegistry(
           Collections.singletonList(
               new NamedWriteableRegistry.Entry(
                   BaseNamedWriteable.class,
                   TestNamedWriteable.NAME,
                   (StreamInput in) ->
                       new TestNamedWriteable(in) {
                         @Override
                         public String getWriteableName() {
                           return "intentionally-broken";
                         }
                       })));
   TestNamedWriteable namedWriteableIn =
       new TestNamedWriteable(
           randomAsciiOfLengthBetween(1, 10), randomAsciiOfLengthBetween(1, 10));
   out.writeNamedWriteable(namedWriteableIn);
   byte[] bytes = BytesReference.toBytes(out.bytes());
   StreamInput in =
       new NamedWriteableAwareStreamInput(StreamInput.wrap(bytes), namedWriteableRegistry);
   assertEquals(in.available(), bytes.length);
   AssertionError e =
       expectThrows(AssertionError.class, () -> in.readNamedWriteable(BaseNamedWriteable.class));
   assertThat(
       e.getMessage(),
       endsWith(
           " claims to have a different name [intentionally-broken] than it was read from [test-named-writeable]."));
 }
 public void testNamedWriteable() throws IOException {
   BytesStreamOutput out = new BytesStreamOutput();
   NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry();
   namedWriteableRegistry.register(
       BaseNamedWriteable.class, TestNamedWriteable.NAME, TestNamedWriteable::new);
   TestNamedWriteable namedWriteableIn =
       new TestNamedWriteable(
           randomAsciiOfLengthBetween(1, 10), randomAsciiOfLengthBetween(1, 10));
   out.writeNamedWriteable(namedWriteableIn);
   byte[] bytes = BytesReference.toBytes(out.bytes());
   StreamInput in =
       new NamedWriteableAwareStreamInput(StreamInput.wrap(bytes), namedWriteableRegistry);
   assertEquals(in.available(), bytes.length);
   BaseNamedWriteable namedWriteableOut = in.readNamedWriteable(BaseNamedWriteable.class);
   assertEquals(namedWriteableOut, namedWriteableIn);
   assertEquals(in.available(), 0);
 }
  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);
  }
 public void testNamedWriteableReaderReturnsNull() throws IOException {
   BytesStreamOutput out = new BytesStreamOutput();
   NamedWriteableRegistry namedWriteableRegistry = new NamedWriteableRegistry();
   namedWriteableRegistry.register(
       BaseNamedWriteable.class, TestNamedWriteable.NAME, (StreamInput in) -> null);
   TestNamedWriteable namedWriteableIn =
       new TestNamedWriteable(
           randomAsciiOfLengthBetween(1, 10), randomAsciiOfLengthBetween(1, 10));
   out.writeNamedWriteable(namedWriteableIn);
   byte[] bytes = BytesReference.toBytes(out.bytes());
   StreamInput in =
       new NamedWriteableAwareStreamInput(StreamInput.wrap(bytes), namedWriteableRegistry);
   assertEquals(in.available(), bytes.length);
   IOException e =
       expectThrows(IOException.class, () -> in.readNamedWriteable(BaseNamedWriteable.class));
   assertThat(
       e.getMessage(),
       endsWith(
           "] returned null which is not allowed and probably means it screwed up the stream."));
 }
  public void testWriteMapOfLists() throws IOException {
    final int size = randomIntBetween(0, 5);
    final Map<String, List<String>> expected = new HashMap<>(size);

    for (int i = 0; i < size; ++i) {
      int listSize = randomIntBetween(0, 5);
      List<String> list = new ArrayList<>(listSize);

      for (int j = 0; j < listSize; ++j) {
        list.add(randomAsciiOfLength(5));
      }

      expected.put(randomAsciiOfLength(2), list);
    }

    final BytesStreamOutput out = new BytesStreamOutput();
    out.writeMapOfLists(expected);

    final StreamInput in = StreamInput.wrap(BytesReference.toBytes(out.bytes()));

    final Map<String, List<String>> loaded = in.readMapOfLists();

    assertThat(loaded.size(), equalTo(expected.size()));

    for (Map.Entry<String, List<String>> entry : expected.entrySet()) {
      assertThat(loaded.containsKey(entry.getKey()), equalTo(true));

      List<String> loadedList = loaded.get(entry.getKey());

      assertThat(loadedList, hasSize(entry.getValue().size()));

      for (int i = 0; i < loadedList.size(); ++i) {
        assertEquals(entry.getValue().get(i), loadedList.get(i));
      }
    }

    assertEquals(0, in.available());

    in.close();
    out.close();
  }
  public void testNamedWriteableList() throws IOException {
    NamedWriteableRegistry namedWriteableRegistry =
        new NamedWriteableRegistry(
            Collections.singletonList(
                new NamedWriteableRegistry.Entry(
                    BaseNamedWriteable.class, TestNamedWriteable.NAME, TestNamedWriteable::new)));
    int size = between(0, 100);
    List<BaseNamedWriteable> expected = new ArrayList<>(size);
    for (int i = 0; i < size; i++) {
      expected.add(
          new TestNamedWriteable(
              randomAsciiOfLengthBetween(1, 10), randomAsciiOfLengthBetween(1, 10)));
    }

    try (BytesStreamOutput out = new BytesStreamOutput()) {
      out.writeNamedWriteableList(expected);
      try (StreamInput in =
          new NamedWriteableAwareStreamInput(out.bytes().streamInput(), namedWriteableRegistry)) {
        assertEquals(expected, in.readNamedWriteableList(BaseNamedWriteable.class));
        assertEquals(0, in.available());
      }
    }
  }
 public void testSimpleStreams() throws Exception {
   assumeTrue("requires a 64-bit JRE ... ?!", Constants.JRE_IS_64BIT);
   BytesStreamOutput out = new BytesStreamOutput();
   out.writeBoolean(false);
   out.writeByte((byte) 1);
   out.writeShort((short) -1);
   out.writeInt(-1);
   out.writeVInt(2);
   out.writeLong(-3);
   out.writeVLong(4);
   out.writeOptionalLong(11234234L);
   out.writeFloat(1.1f);
   out.writeDouble(2.2);
   int[] intArray = {1, 2, 3};
   out.writeGenericValue(intArray);
   int[] vIntArray = {4, 5, 6};
   out.writeVIntArray(vIntArray);
   long[] longArray = {1, 2, 3};
   out.writeGenericValue(longArray);
   long[] vLongArray = {4, 5, 6};
   out.writeVLongArray(vLongArray);
   float[] floatArray = {1.1f, 2.2f, 3.3f};
   out.writeGenericValue(floatArray);
   double[] doubleArray = {1.1, 2.2, 3.3};
   out.writeGenericValue(doubleArray);
   out.writeString("hello");
   out.writeString("goodbye");
   out.writeGenericValue(BytesRefs.toBytesRef("bytesref"));
   out.writeStringArray(new String[] {"a", "b", "cat"});
   out.writeBytesReference(new BytesArray("test"));
   out.writeOptionalBytesReference(new BytesArray("test"));
   out.writeOptionalDouble(null);
   out.writeOptionalDouble(1.2);
   out.writeTimeZone(DateTimeZone.forID("CET"));
   out.writeOptionalTimeZone(DateTimeZone.getDefault());
   out.writeOptionalTimeZone(null);
   final byte[] bytes = BytesReference.toBytes(out.bytes());
   StreamInput in = StreamInput.wrap(BytesReference.toBytes(out.bytes()));
   assertEquals(in.available(), bytes.length);
   assertThat(in.readBoolean(), equalTo(false));
   assertThat(in.readByte(), equalTo((byte) 1));
   assertThat(in.readShort(), equalTo((short) -1));
   assertThat(in.readInt(), equalTo(-1));
   assertThat(in.readVInt(), equalTo(2));
   assertThat(in.readLong(), equalTo(-3L));
   assertThat(in.readVLong(), equalTo(4L));
   assertThat(in.readOptionalLong(), equalTo(11234234L));
   assertThat((double) in.readFloat(), closeTo(1.1, 0.0001));
   assertThat(in.readDouble(), closeTo(2.2, 0.0001));
   assertThat(in.readGenericValue(), equalTo((Object) intArray));
   assertThat(in.readVIntArray(), equalTo(vIntArray));
   assertThat(in.readGenericValue(), equalTo((Object) longArray));
   assertThat(in.readVLongArray(), equalTo(vLongArray));
   assertThat(in.readGenericValue(), equalTo((Object) floatArray));
   assertThat(in.readGenericValue(), equalTo((Object) doubleArray));
   assertThat(in.readString(), equalTo("hello"));
   assertThat(in.readString(), equalTo("goodbye"));
   assertThat(in.readGenericValue(), equalTo((Object) BytesRefs.toBytesRef("bytesref")));
   assertThat(in.readStringArray(), equalTo(new String[] {"a", "b", "cat"}));
   assertThat(in.readBytesReference(), equalTo(new BytesArray("test")));
   assertThat(in.readOptionalBytesReference(), equalTo(new BytesArray("test")));
   assertNull(in.readOptionalDouble());
   assertThat(in.readOptionalDouble(), closeTo(1.2, 0.0001));
   assertEquals(DateTimeZone.forID("CET"), in.readTimeZone());
   assertEquals(DateTimeZone.getDefault(), in.readOptionalTimeZone());
   assertNull(in.readOptionalTimeZone());
   assertEquals(0, in.available());
   in.close();
   out.close();
 }