/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.kafka.common.serialization;
import org.apache.kafka.common.errors.SerializationException;
import org.junit.Test;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsNull.nullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
public class SerializationTest {
final private String topic = "testTopic";
private class DummyClass {
}
@Test
public void testSerdeFrom() {
Serde<Long> thisSerde = Serdes.serdeFrom(Long.class);
Serde<Long> otherSerde = Serdes.Long();
Long value = 423412424L;
assertEquals("Should get the original long after serialization and deserialization",
value, thisSerde.deserializer().deserialize(topic, otherSerde.serializer().serialize(topic, value)));
assertEquals("Should get the original long after serialization and deserialization",
value, otherSerde.deserializer().deserialize(topic, thisSerde.serializer().serialize(topic, value)));
}
@Test(expected = IllegalArgumentException.class)
public void testSerdeFromUnknown() {
Serdes.serdeFrom(DummyClass.class);
}
@Test(expected = IllegalArgumentException.class)
public void testSerdeFromNotNull() {
Serdes.serdeFrom(null, Serdes.Long().deserializer());
}
@Test
public void testStringSerializer() {
String str = "my string";
List<String> encodings = new ArrayList<String>();
encodings.add("UTF8");
encodings.add("UTF-16");
for (String encoding : encodings) {
Serde<String> serDeser = getStringSerde(encoding);
Serializer<String> serializer = serDeser.serializer();
Deserializer<String> deserializer = serDeser.deserializer();
assertEquals("Should get the original string after serialization and deserialization with encoding " + encoding,
str, deserializer.deserialize(topic, serializer.serialize(topic, str)));
assertEquals("Should support null in serialization and deserialization with encoding " + encoding,
null, deserializer.deserialize(topic, serializer.serialize(topic, null)));
}
}
@Test
public void testIntegerSerializer() {
Integer[] integers = new Integer[]{
423412424,
-41243432
};
Serializer<Integer> serializer = Serdes.Integer().serializer();
Deserializer<Integer> deserializer = Serdes.Integer().deserializer();
for (Integer integer : integers) {
assertEquals("Should get the original integer after serialization and deserialization",
integer, deserializer.deserialize(topic, serializer.serialize(topic, integer)));
}
assertEquals("Should support null in serialization and deserialization",
null, deserializer.deserialize(topic, serializer.serialize(topic, null)));
serializer.close();
deserializer.close();
}
@Test
public void testLongSerializer() {
Long[] longs = new Long[]{
922337203685477580L,
-922337203685477581L
};
Serializer<Long> serializer = Serdes.Long().serializer();
Deserializer<Long> deserializer = Serdes.Long().deserializer();
for (Long value : longs) {
assertEquals("Should get the original long after serialization and deserialization",
value, deserializer.deserialize(topic, serializer.serialize(topic, value)));
}
assertEquals("Should support null in serialization and deserialization",
null, deserializer.deserialize(topic, serializer.serialize(topic, null)));
serializer.close();
deserializer.close();
}
@Test
public void shouldSerializeDeserializeFloat() {
final Float[] floats = new Float[]{
5678567.12312f,
-5678567.12341f
};
final Serializer<Float> serializer = Serdes.Float().serializer();
final Deserializer<Float> deserializer = Serdes.Float().deserializer();
for (final Float value : floats) {
assertThat("Should round-trip a float",
value, equalTo(deserializer.deserialize(topic, serializer.serialize(topic, value))));
}
serializer.close();
deserializer.close();
}
@Test
public void floatSerializerShouldReturnNullForNull() {
final Serializer<Float> serializer = Serdes.Float().serializer();
assertThat(serializer.serialize(topic, null), nullValue());
serializer.close();
}
@Test
public void floatDeserializerShouldReturnNullForNull() {
final Deserializer<Float> deserializer = Serdes.Float().deserializer();
assertThat(deserializer.deserialize(topic, null), nullValue());
deserializer.close();
}
@Test
public void floatDeserializerShouldThrowSerializationExceptionOnZeroBytes() {
final Deserializer<Float> deserializer = Serdes.Float().deserializer();
try {
deserializer.deserialize(topic, new byte[0]);
fail("Should have thrown a SerializationException because of zero input bytes");
} catch (SerializationException e) {
// Ignore (there's no contract on the details of the exception)
}
deserializer.close();
}
@Test
public void floatDeserializerShouldThrowSerializationExceptionOnTooFewBytes() {
final Deserializer<Float> deserializer = Serdes.Float().deserializer();
try {
deserializer.deserialize(topic, new byte[3]);
fail("Should have thrown a SerializationException because of too few input bytes");
} catch (SerializationException e) {
// Ignore (there's no contract on the details of the exception)
}
deserializer.close();
}
@Test
public void floatDeserializerShouldThrowSerializationExceptionOnTooManyBytes() {
final Deserializer<Float> deserializer = Serdes.Float().deserializer();
try {
deserializer.deserialize(topic, new byte[5]);
fail("Should have thrown a SerializationException because of too many input bytes");
} catch (SerializationException e) {
// Ignore (there's no contract on the details of the exception)
}
deserializer.close();
}
@Test
public void floatSerdeShouldPreserveNaNValues() {
final int someNaNAsIntBits = 0x7f800001;
final float someNaN = Float.intBitsToFloat(someNaNAsIntBits);
final int anotherNaNAsIntBits = 0x7f800002;
final float anotherNaN = Float.intBitsToFloat(anotherNaNAsIntBits);
final Serde<Float> serde = Serdes.Float();
// Because of NaN semantics we must assert based on the raw int bits.
final Float roundtrip = serde.deserializer().deserialize(topic,
serde.serializer().serialize(topic, someNaN));
assertThat(Float.floatToRawIntBits(roundtrip), equalTo(someNaNAsIntBits));
final Float otherRoundtrip = serde.deserializer().deserialize(topic,
serde.serializer().serialize(topic, anotherNaN));
assertThat(Float.floatToRawIntBits(otherRoundtrip), equalTo(anotherNaNAsIntBits));
serde.close();
}
@Test
public void testDoubleSerializer() {
Double[] doubles = new Double[]{
5678567.12312d,
-5678567.12341d
};
Serializer<Double> serializer = Serdes.Double().serializer();
Deserializer<Double> deserializer = Serdes.Double().deserializer();
for (Double value : doubles) {
assertEquals("Should get the original double after serialization and deserialization",
value, deserializer.deserialize(topic, serializer.serialize(topic, value)));
}
assertEquals("Should support null in serialization and deserialization",
null, deserializer.deserialize(topic, serializer.serialize(topic, null)));
serializer.close();
deserializer.close();
}
@Test
public void testByteBufferSerializer() {
ByteBuffer buf = ByteBuffer.allocate(10);
buf.put("my string".getBytes());
Serializer<ByteBuffer> serializer = Serdes.ByteBuffer().serializer();
Deserializer<ByteBuffer> deserializer = Serdes.ByteBuffer().deserializer();
assertEquals("Should get the original ByteBuffer after serialization and deserialization",
buf, deserializer.deserialize(topic, serializer.serialize(topic, buf)));
assertEquals("Should support null in serialization and deserialization",
null, deserializer.deserialize(topic, serializer.serialize(topic, null)));
serializer.close();
deserializer.close();
}
private Serde<String> getStringSerde(String encoder) {
Map<String, Object> serializerConfigs = new HashMap<String, Object>();
serializerConfigs.put("key.serializer.encoding", encoder);
Serializer<String> serializer = Serdes.String().serializer();
serializer.configure(serializerConfigs, true);
Map<String, Object> deserializerConfigs = new HashMap<String, Object>();
deserializerConfigs.put("key.deserializer.encoding", encoder);
Deserializer<String> deserializer = Serdes.String().deserializer();
deserializer.configure(deserializerConfigs, true);
return Serdes.serdeFrom(serializer, deserializer);
}
}