/*
* Copyright (C) 2015 SoftIndex LLC.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.datakernel.serializer;
import io.datakernel.codegen.DefiningClassLoader;
import io.datakernel.serializer.annotations.Deserialize;
import io.datakernel.serializer.annotations.Serialize;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static io.datakernel.bytebuf.ByteBufPool.*;
import static io.datakernel.serializer.DataOutputStreamEx.*;
import static io.datakernel.serializer.asm.BufferSerializers.*;
import static org.junit.Assert.*;
public class SerializeStreamTest {
@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 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 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 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 testChangeInputStream() throws IOException, SerializeException, DeserializeException {
final Integer[] integers1 = new Integer[]{10, 20, 30, 42};
final Integer[] integers2 = new Integer[]{10, 20, 30, 42};
ByteArrayOutputStream byteOutputStream1 = new ByteArrayOutputStream();
try (DataOutputStreamEx dataOutputStream1 = DataOutputStreamEx.create(byteOutputStream1, 30)) {
for (Integer integer : integers1) {
dataOutputStream1.serialize(intSerializer(), integer, MAX_SIZE_127);
}
}
ByteArrayOutputStream byteOutputStream2 = new ByteArrayOutputStream();
try (DataOutputStreamEx dataOutputStream2 = DataOutputStreamEx.create(byteOutputStream2, 30)) {
for (Integer integer : integers2) {
dataOutputStream2.serialize(intSerializer(), integer, MAX_SIZE_127);
}
}
ByteArrayInputStream byteInputStream1 = new ByteArrayInputStream(byteOutputStream1.toByteArray());
ByteArrayInputStream byteInputStream2 = new ByteArrayInputStream(byteOutputStream2.toByteArray());
try (DataInputStreamEx dataInputStream = DataInputStreamEx.create(byteInputStream1, 10)) {
for (Integer integer : integers1) {
assertEquals(integer, dataInputStream.deserialize(intSerializer()));
}
dataInputStream.changeInputStream(byteInputStream2);
for (Integer integer : integers2) {
assertEquals(integer, dataInputStream.deserialize(intSerializer()));
}
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 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 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());
}
@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 testStandardWrite() throws IOException {
final ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
try (final DataOutputStreamEx dataOutputStream = DataOutputStreamEx.create(byteOutputStream, 1)) {
dataOutputStream.writeInt(42);
dataOutputStream.writeBoolean(false);
dataOutputStream.writeByte((byte) 43);
dataOutputStream.writeChar((char) 44);
dataOutputStream.writeDouble(45.46);
dataOutputStream.writeFloat(47.48f);
dataOutputStream.writeIso88591("49");
dataOutputStream.writeIso88591("");// check specific situation
dataOutputStream.writeLong(50L);
dataOutputStream.writeShort((short) 51);
dataOutputStream.writeUTF8("test 52");
dataOutputStream.writeUTF8("");// check specific situation
dataOutputStream.writeUTF16("тест 53");
dataOutputStream.writeUTF16("");// check specific situation
dataOutputStream.writeVarInt(-54);
dataOutputStream.writeVarLong(-55);
dataOutputStream.write(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
dataOutputStream.write(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, 5, 2);
}
final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
try (final DataInputStreamEx dataInputStream = DataInputStreamEx.create(byteArrayInputStream)) {
assertEquals(42, dataInputStream.readInt());
assertEquals(false, dataInputStream.readBoolean());
assertEquals((byte) 43, dataInputStream.readByte());
assertEquals((char) 44, dataInputStream.readChar());
assertEquals(45.46, dataInputStream.readDouble(), 1e-6);
assertEquals(47.48f, dataInputStream.readFloat(), 1e-6);
assertEquals("49", dataInputStream.readIso88591());
assertEquals("", dataInputStream.readIso88591()); // check specific situation
assertEquals(50L, dataInputStream.readLong());
assertEquals((short) 51, dataInputStream.readShort());
assertEquals("test 52", dataInputStream.readUTF8());
assertEquals("", dataInputStream.readUTF8()); // check specific situation
assertEquals("тест 53", dataInputStream.readUTF16());
assertEquals("", dataInputStream.readUTF16()); // check specific situation
assertEquals(-54, dataInputStream.readVarInt());
assertEquals(-55, dataInputStream.readVarLong());
assertArrayEquals(new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, read(dataInputStream, new byte[10]));
assertArrayEquals(new byte[]{0, 0, 0, 0, 0, 6, 7, 0, 0, 0}, read(dataInputStream, new byte[10], 5, 2));
assertTrue(dataInputStream.isEndOfStream());
}
assertEquals(getPoolItemsString(), getCreatedItems(), getPoolItems());
}
@Test(expected = IOException.class)
public void testReadInvalidHeader() throws IOException, DeserializeException {
DataInputStreamEx.create(new ByteArrayInputStream(new byte[]{-1, -1, -1, -1})).deserialize(intSerializer());
}
private static byte[] read(DataInputStreamEx dataInputStream, byte[] bytes) throws IOException {
dataInputStream.read(bytes);
return bytes;
}
private static byte[] read(DataInputStreamEx dataInputStream, byte[] bytes, int off, int len) throws IOException {
dataInputStream.read(bytes, off, len);
return bytes;
}
private static byte[] createTestByteArray(int length, byte fillValue) {
byte[] array = new byte[length];
Arrays.fill(array, fillValue);
return array;
}
public static class TestClass {
@Serialize(order = 0)
public final String str;
public TestClass(@Deserialize("str") String str) {
this.str = str;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestClass testClass = (TestClass) o;
return str != null ? str.equals(testClass.str) : testClass.str == null;
}
@Override
public int hashCode() {
return str != null ? str.hashCode() : 0;
}
}
}