package com.ctriposs.baiji; import com.ctriposs.baiji.exception.BaijiRuntimeException; import com.ctriposs.baiji.schema.RecordSchema; import com.ctriposs.baiji.specific.SpecificRecord; import com.ctriposs.baiji.specific.SpecificRecordBase; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.List; import java.util.Map; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; public class BinarySerializerTest { @Test public void testEnumResolution() throws IOException { EnumRecord testRecord = new EnumRecord(); testRecord.enumType = EnumType.SECOND; testRecord.enumTypeExplicit = EnumTypeExplicit.SECOND; // serialize byte[] data = serialize(testRecord); // deserialize EnumRecord rec2 = deserialize(data, EnumRecord.class); assertEquals(testRecord.enumType, rec2.enumType); assertEquals(testRecord.enumTypeExplicit, rec2.enumTypeExplicit); } private static <S extends SpecificRecord> S deserialize(byte[] data, Class<S> clazz) throws IOException { ByteArrayInputStream is = new ByteArrayInputStream(data); Serializer serializer = new BinarySerializer(); S output = serializer.deserialize(clazz, is); assertEquals(0, is.available()); // Ensure we have read everything. checkAlternateDeserializers(output, clazz, data); return output; } private static <S extends SpecificRecord> void checkAlternateDeserializers(S expected, Class<S> clazz, byte[] data) throws IOException { ByteArrayInputStream is = new ByteArrayInputStream(data); Serializer serializer = new BinarySerializer(); S output = serializer.deserialize(clazz, is); assertEquals(0, is.available()); // Ensure we have read everything. assertSpecificRecordEqual(expected, output); } private static void assertSpecificRecordEqual(SpecificRecord rec1, SpecificRecord rec2) { RecordSchema recordSchema = (RecordSchema) rec1.getSchema(); for (int i = 0; i < recordSchema.size(); i++) { Object rec1Val = rec1.get(i); Object rec2Val = rec2.get(i); if (rec1Val instanceof SpecificRecord) { assertSpecificRecordEqual((SpecificRecord) rec1Val, (SpecificRecord) rec2Val); } else if (rec1Val instanceof List) { List rec1List = (List) rec1Val; if (!rec1List.isEmpty() && rec1List.get(0) instanceof SpecificRecord) { List rec2List = (List) rec2Val; assertEquals(rec1List.size(), rec2List.size()); for (int j = 0; j < rec1List.size(); j++) { assertSpecificRecordEqual((SpecificRecord) rec1List.get(j), (SpecificRecord) rec2List.get(j)); } } else { assertEquals(rec1Val, rec2Val); } } else if (rec1Val instanceof Map) { Map rec1Dict = (Map) rec1Val; Map rec2Dict = (Map) rec2Val; assertEquals(rec2Dict.size(), rec2Dict.size()); for (Object key : rec1Dict.keySet()) { Object val1 = rec1Dict.get(key); Object val2 = rec2Dict.get(key); if (val1 instanceof SpecificRecord) { assertSpecificRecordEqual((SpecificRecord) val1, (SpecificRecord) val2); } else { assertEquals(val1, val2); } } } else { assertEquals(rec1Val, rec2Val); } } } private static <T extends SpecificRecord> byte[] serialize(T actual) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); Serializer serliazer = new BinarySerializer(); serliazer.serialize(actual, os); byte[] data = os.toByteArray(); checkAlternateSerializers(data, actual); return data; } private static <T extends SpecificRecord> void checkAlternateSerializers(byte[] expected, T value) throws IOException { ByteArrayOutputStream os = new ByteArrayOutputStream(); Serializer serliazer = new BinarySerializer(); serliazer.serialize(value, os); byte[] output = os.toByteArray(); assertEquals(expected.length, output.length); assertArrayEquals(expected, output); } } enum EnumType { FIRST(0), SECOND(1), THIRD(2), FOUR(3); private final int _value; EnumType(int value) { _value = value; } public int getValue() { return _value; } public static EnumType findByValue(int value) { switch (value) { case 0: return FIRST; case 1: return SECOND; case 2: return THIRD; case 3: return FOUR; default: return null; } } } enum EnumTypeExplicit { THIRD(3), FOUR(4), FIRST(1), SECOND(2); private final int _value; EnumTypeExplicit(int value) { _value = value; } public int getValue() { return _value; } public static EnumTypeExplicit findByValue(int value) { switch (value) { case 1: return FIRST; case 2: return SECOND; case 3: return THIRD; case 4: return FOUR; default: return null; } } } class EnumRecord extends SpecificRecordBase { public static final com.ctriposs.baiji.schema.Schema SCHEMA = com.ctriposs.baiji.schema.Schema.parse( "{\"type\":\"record\",\"name\":\"EnumRecord\",\"namespace\":\"com.ctriposs.baiji\"," + "\"fields\":[{\"name\":\"enumType\",\"type\": { \"type\": \"enum\", \"name\":" + " \"EnumType\", \"symbols\": [\"FIRST\", \"SECOND\", \"THIRD\", \"FOUR\"]} }," + "{\"name\":\"enumTypeExplicit\",\"type\": { \"type\": \"enum\", \"name\":" + " \"EnumTypeExplicit\", \"symbols\": [{\"name\": \"THIRD\", \"value\": 3}, \"FOUR\", {\"name\": \"FIRST\", \"value\": 1}, \"SECOND\"]} }]}"); public EnumType enumType; public EnumTypeExplicit enumTypeExplicit; public EnumRecord() { } public com.ctriposs.baiji.schema.Schema getSchema() { return SCHEMA; } public EnumType getEnumType() { return enumType; } public void setEnumType(EnumType enumType) { this.enumType = enumType; } public EnumTypeExplicit getEnumTypeExplicit() { return enumTypeExplicit; } public void setEnumTypeExplicit(EnumTypeExplicit enumTypeExplicit) { this.enumTypeExplicit = enumTypeExplicit; } @Override public Object get(int fieldPos) { switch (fieldPos) { case 0: return enumType; case 1: return enumTypeExplicit; default: throw new BaijiRuntimeException("Bad index " + fieldPos + " in Get()"); } } @Override public void put(int fieldPos, Object fieldValue) { switch (fieldPos) { case 0: enumType = (EnumType) fieldValue; break; case 1: enumTypeExplicit = (EnumTypeExplicit) fieldValue; break; default: throw new BaijiRuntimeException("Bad index " + fieldPos + " in Put()"); } } }