@Test
  public void testRestorePositionAfterException() throws Exception {
    TestClass validObj1 = new TestClass("abc");
    TestClass validObj2 = new TestClass("=xyz=");
    TestClass invalidObj = new TestClass(null);
    BufferSerializer<TestClass> serializer =
        SerializerBuilder.create(DefiningClassLoader.create()).build(TestClass.class);

    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    try (DataOutputStreamEx dataOutputStream = DataOutputStreamEx.create(byteOutputStream)) {
      dataOutputStream.serialize(serializer, validObj1, MAX_SIZE_127);
      try {
        dataOutputStream.serialize(serializer, invalidObj, MAX_SIZE_127);
      } catch (SerializeException ignored) {
      }
      dataOutputStream.serialize(serializer, validObj2, MAX_SIZE_127);
    }

    ByteArrayInputStream byteArrayInputStream =
        new ByteArrayInputStream(byteOutputStream.toByteArray());
    try (DataInputStreamEx dataInputStream = DataInputStreamEx.create(byteArrayInputStream)) {
      assertEquals(validObj1.str, dataInputStream.deserialize(serializer).str);
      assertEquals(validObj2.str, dataInputStream.deserialize(serializer).str);
      assertTrue(dataInputStream.isEndOfStream());
    }

    assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
  }
  @Test
  public void testRestorePositionAfterSizeException() throws Exception {
    byte[] array1 = createTestByteArray(100, (byte) 10);
    byte[] array2 = createTestByteArray(100, (byte) 20);
    byte[] tooBigArray = createTestByteArray(150, (byte) 30);

    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    try (DataOutputStreamEx dataOutputStream = DataOutputStreamEx.create(byteOutputStream)) {
      dataOutputStream.serialize(bytesSerializer(), array1, MAX_SIZE_127);
      try {
        dataOutputStream.serialize(bytesSerializer(), tooBigArray, MAX_SIZE_127);
      } catch (SerializeException ignored) {
      }
      dataOutputStream.serialize(bytesSerializer(), array2, MAX_SIZE_127);
    }

    ByteArrayInputStream byteArrayInputStream =
        new ByteArrayInputStream(byteOutputStream.toByteArray());
    try (DataInputStreamEx dataInputStream = DataInputStreamEx.create(byteArrayInputStream)) {
      assertArrayEquals(array1, dataInputStream.deserialize(bytesSerializer()));
      assertArrayEquals(array2, dataInputStream.deserialize(bytesSerializer()));
      assertTrue(dataInputStream.isEndOfStream());
    }

    assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
  }
  @Test
  public void test() throws IOException, SerializeException, DeserializeException {
    String[] strings = new String[] {"test1-string", "test2-int", "test3-t", "test4-str"};
    BufferSerializer<String> bufferSerializer =
        SerializerBuilder.create(DefiningClassLoader.create()).build(String.class);

    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    try (DataOutputStreamEx dataOutputStream = DataOutputStreamEx.create(byteOutputStream, 30)) {
      for (String string : strings) {
        dataOutputStream.serialize(bufferSerializer, string, MAX_SIZE_127);
      }
    }

    ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
    try (DataInputStreamEx dataInputStream = DataInputStreamEx.create(byteInputStream, 50)) {
      final List<String> newStrings = new ArrayList<>(4);
      while (!dataInputStream.isEndOfStream()) {
        newStrings.add(dataInputStream.deserialize(bufferSerializer));
      }

      assertArrayEquals(strings, newStrings.toArray(new String[4]));
      assertTrue(dataInputStream.isEndOfStream());
    }

    assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
  }
  @Test
  public void testHeaderSize() throws IOException, SerializeException, DeserializeException {
    final ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    try (final DataOutputStreamEx dataOutputStream =
        DataOutputStreamEx.create(byteOutputStream, 1)) {
      dataOutputStream.serialize(intSerializer(), 42, MAX_SIZE_127);
      dataOutputStream.serialize(intSerializer(), 42, MAX_SIZE_16K);
      dataOutputStream.serialize(intSerializer(), 42, MAX_SIZE_2M);
    }

    final ByteArrayInputStream byteArrayInputStream =
        new ByteArrayInputStream(byteOutputStream.toByteArray());
    try (final DataInputStreamEx dataInputStream = DataInputStreamEx.create(byteArrayInputStream)) {
      assertEquals(Integer.valueOf(42), dataInputStream.deserialize(intSerializer()));
      assertEquals(Integer.valueOf(42), dataInputStream.deserialize(intSerializer()));
      assertEquals(Integer.valueOf(42), dataInputStream.deserialize(intSerializer()));
      assertTrue(dataInputStream.isEndOfStream());
    }

    assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
  }
  @Test
  public void testChangeOutputStream()
      throws IOException, SerializeException, DeserializeException {
    final Integer[] integers1 = new Integer[] {10, 20, 30, 42};
    final Integer[] integers2 = new Integer[] {100, 200, 300, 420};

    ByteArrayOutputStream byteOutputStream1 = new ByteArrayOutputStream();
    ByteArrayOutputStream byteOutputStream2 = new ByteArrayOutputStream();
    try (DataOutputStreamEx dataOutputStream = DataOutputStreamEx.create(byteOutputStream1, 30)) {
      for (Integer integer : integers1) {
        dataOutputStream.serialize(intSerializer(), integer, MAX_SIZE_127);
      }

      dataOutputStream.changeOutputStream(byteOutputStream2);
      for (Integer integer : integers2) {
        dataOutputStream.serialize(intSerializer(), integer, MAX_SIZE_127);
      }
    }

    ByteArrayInputStream byteInputStream1 =
        new ByteArrayInputStream(byteOutputStream1.toByteArray());
    ByteArrayInputStream byteInputStream2 =
        new ByteArrayInputStream(byteOutputStream2.toByteArray());

    try (DataInputStreamEx dataInputStream1 = DataInputStreamEx.create(byteInputStream1, 10);
        DataInputStreamEx dataInputStream2 = DataInputStreamEx.create(byteInputStream2, 10)) {
      for (Integer integer : integers1) {
        assertEquals(integer, dataInputStream1.deserialize(intSerializer()));
      }

      for (Integer integer : integers2) {
        assertEquals(integer, dataInputStream2.deserialize(intSerializer()));
      }
      assertTrue(dataInputStream1.isEndOfStream());
      assertTrue(dataInputStream2.isEndOfStream());
    }

    assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
  }
  @Test
  public void testInteger() throws IOException, SerializeException, DeserializeException {
    final Integer[] integers = new Integer[] {10, 20, 30, 42};

    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    try (DataOutputStreamEx dataOutputStream = DataOutputStreamEx.create(byteOutputStream, 30)) {
      for (Integer integer : integers) {
        dataOutputStream.serialize(intSerializer(), integer, MAX_SIZE_127);
      }
    }

    ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
    try (DataInputStreamEx dataInputStream = DataInputStreamEx.create(byteInputStream, 10)) {
      for (Integer integer : integers) {
        assertEquals(integer, dataInputStream.deserialize(intSerializer()));
      }
      assertTrue(dataInputStream.isEndOfStream());
    }

    assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
  }
  @Test
  public void testLittleBuffer() throws IOException, SerializeException, DeserializeException {
    String[] strings = new String[] {"test1-string", "test2-int", "test3-t", "test4-str"};

    ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    try (DataOutputStreamEx dataOutputStream = DataOutputStreamEx.create(byteOutputStream, 30)) {
      for (String string : strings) {
        dataOutputStream.serialize(utf8Serializer(), string, MAX_SIZE_127);
      }
    }

    ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
    try (DataInputStreamEx dataInputStream = DataInputStreamEx.create(byteInputStream, 3)) {
      for (String string : strings) {
        assertEquals(string, dataInputStream.deserialize(utf8Serializer()));
      }

      assertTrue(dataInputStream.isEndOfStream());
    }

    assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
  }
  @Test
  public void testStartBufferLessThanMessage()
      throws IOException, SerializeException, DeserializeException {
    final BufferSerializer<TestClass> serializer =
        SerializerBuilder.create(DefiningClassLoader.create()).build(TestClass.class);
    final TestClass validObj1 = new TestClass("22222");

    final ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
    try (final DataOutputStreamEx dataOutputStream =
        DataOutputStreamEx.create(byteOutputStream, 1)) {
      dataOutputStream.serialize(serializer, validObj1, MAX_SIZE_127);
    }

    final ByteArrayInputStream byteArrayInputStream =
        new ByteArrayInputStream(byteOutputStream.toByteArray());
    try (final DataInputStreamEx dataInputStream = DataInputStreamEx.create(byteArrayInputStream)) {
      assertEquals(validObj1, dataInputStream.deserialize(serializer));
      assertTrue(dataInputStream.isEndOfStream());
    }

    assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
  }