/* * 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.hadoop.hive.serde2.avro; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.nio.ByteBuffer; import java.rmi.server.UID; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.List; import java.util.Map; import org.apache.avro.Schema; import org.apache.avro.generic.GenericData; import org.apache.hadoop.hive.serde2.SerDeException; import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.StandardListObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.StandardStructObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.StructField; import org.apache.hadoop.hive.serde2.objectinspector.UnionObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.JavaStringObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector; import org.apache.hadoop.hive.serde2.objectinspector.primitive.VoidObjectInspector; import org.junit.Test; public class TestAvroDeserializer { private final GenericData GENERIC_DATA = GenericData.get(); @Test public void canDeserializeVoidType() throws IOException, SerDeException { String schemaString = "{\n" + " \"type\": \"record\", \n" + " \"name\": \"nullTest\",\n" + " \"fields\" : [\n" + " {\"name\": \"isANull\", \"type\": \"null\"}\n" + " ]\n" + "}"; Schema s = AvroSerdeUtils.getSchemaFor(schemaString); GenericData.Record record = new GenericData.Record(s); record.put("isANull", null); assertTrue(GENERIC_DATA.validate(s, record)); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); Object theVoidObject = row.get(0); assertNull(theVoidObject); StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); StructField fieldRef = oi.getStructFieldRef("isANull"); Object shouldBeNull = oi.getStructFieldData(row, fieldRef); assertNull(shouldBeNull); assertTrue(fieldRef.getFieldObjectInspector() instanceof VoidObjectInspector); } @Test public void canDeserializeMapsWithPrimitiveKeys() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.MAP_WITH_PRIMITIVE_VALUE_TYPE); GenericData.Record record = new GenericData.Record(s); Map<String, Long> m = new Hashtable<String, Long>(); m.put("one", 1l); m.put("two", 2l); m.put("three", 3l); record.put("aMap", m); assertTrue(GENERIC_DATA.validate(s, record)); System.out.println("record = " + record); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); Object theMapObject = row.get(0); assertTrue(theMapObject instanceof Map); Map theMap = (Map)theMapObject; // Verify the raw object that's been created assertEquals(1l, theMap.get("one")); assertEquals(2l, theMap.get("two")); assertEquals(3l, theMap.get("three")); // Verify that the provided object inspector can pull out these same values StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); List<Object> z = oi.getStructFieldsDataAsList(row); assertEquals(1, z.size()); StructField fieldRef = oi.getStructFieldRef("amap"); Map theMap2 = (Map)oi.getStructFieldData(row, fieldRef); assertEquals(1l, theMap2.get("one")); assertEquals(2l, theMap2.get("two")); assertEquals(3l, theMap2.get("three")); } @Test public void canDeserializeArrays() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.ARRAY_WITH_PRIMITIVE_ELEMENT_TYPE); GenericData.Record record = new GenericData.Record(s); List<String> list = new ArrayList<String>(); list.add("Eccleston"); list.add("Tennant"); list.add("Smith"); record.put("anArray", list); assertTrue(GENERIC_DATA.validate(s, record)); System.out.println("Array-backed record = " + record); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); Object theArrayObject = row.get(0); assertTrue(theArrayObject instanceof List); List theList = (List)theArrayObject; // Verify the raw object that's been created assertEquals("Eccleston", theList.get(0)); assertEquals("Tennant", theList.get(1)); assertEquals("Smith", theList.get(2)); // Now go the correct way, through objectinspectors StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); StructField fieldRefToArray = oi.getStructFieldRef("anArray"); Object anArrayData = oi.getStructFieldData(row, fieldRefToArray); StandardListObjectInspector anArrayOI = (StandardListObjectInspector)fieldRefToArray.getFieldObjectInspector(); assertEquals(3, anArrayOI.getListLength(anArrayData)); JavaStringObjectInspector elementOI = (JavaStringObjectInspector)anArrayOI.getListElementObjectInspector(); Object firstElement = anArrayOI.getListElement(anArrayData, 0); assertEquals("Eccleston", elementOI.getPrimitiveJavaObject(firstElement)); assertTrue(firstElement instanceof String); Object secondElement = anArrayOI.getListElement(anArrayData, 1); assertEquals("Tennant", elementOI.getPrimitiveJavaObject(secondElement)); assertTrue(secondElement instanceof String); Object thirdElement = anArrayOI.getListElement(anArrayData, 2); assertEquals("Smith", elementOI.getPrimitiveJavaObject(thirdElement)); assertTrue(thirdElement instanceof String); } public void canDeserializeRecordsInternal(Schema s, Schema fileSchema) throws SerDeException, IOException { GenericData.Record record = new GenericData.Record(s); GenericData.Record innerRecord = new GenericData.Record(s.getField("aRecord").schema()); innerRecord.put("int1", 42); innerRecord.put("boolean1", true); innerRecord.put("long1", 42432234234l); record.put("aRecord", innerRecord); assertTrue(GENERIC_DATA.validate(s, record)); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record, fileSchema); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); Object theRecordObject = row.get(0); System.out.println("theRecordObject = " + theRecordObject.getClass().getCanonicalName()); // The original record was lost in the deserialization, so just go the // correct way, through objectinspectors StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); List<? extends StructField> allStructFieldRefs = oi.getAllStructFieldRefs(); assertEquals(1, allStructFieldRefs.size()); StructField fieldRefForaRecord = allStructFieldRefs.get(0); assertEquals("arecord", fieldRefForaRecord.getFieldName()); Object innerRecord2 = oi.getStructFieldData(row, fieldRefForaRecord); // Extract innerRecord field refs StandardStructObjectInspector innerRecord2OI = (StandardStructObjectInspector) fieldRefForaRecord.getFieldObjectInspector(); List<? extends StructField> allStructFieldRefs1 = innerRecord2OI.getAllStructFieldRefs(); assertEquals(3, allStructFieldRefs1.size()); assertEquals("int1", allStructFieldRefs1.get(0).getFieldName()); assertEquals("boolean1", allStructFieldRefs1.get(1).getFieldName()); assertEquals("long1", allStructFieldRefs1.get(2).getFieldName()); innerRecord2OI.getStructFieldsDataAsList(innerRecord2); assertEquals(42, innerRecord2OI.getStructFieldData(innerRecord2, allStructFieldRefs1.get(0))); assertEquals(true, innerRecord2OI.getStructFieldData(innerRecord2, allStructFieldRefs1.get(1))); assertEquals(42432234234l, innerRecord2OI.getStructFieldData(innerRecord2, allStructFieldRefs1.get(2))); } @Test public void canDeserializeRecords() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.RECORD_SCHEMA); canDeserializeRecordsInternal(s, s); } @Test public void canDeserializeNullableRecords() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.RECORD_SCHEMA); Schema fileSchema = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.NULLABLE_RECORD_SCHEMA); canDeserializeRecordsInternal(s, fileSchema); } private class ResultPair { // Because Pairs give Java the vapors. public final ObjectInspector oi; public final Object value; public final Object unionObject; private ResultPair(ObjectInspector oi, Object value, Object unionObject) { this.oi = oi; this.value = value; this.unionObject = unionObject; } } @Test public void canDeserializeUnions() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.UNION_SCHEMA); GenericData.Record record = new GenericData.Record(s); record.put("aUnion", "this is a string"); ResultPair result = unionTester(s, record); assertTrue(result.value instanceof String); assertEquals("this is a string", result.value); UnionObjectInspector uoi = (UnionObjectInspector)result.oi; assertEquals(1, uoi.getTag(result.unionObject)); // Now the other enum possibility record = new GenericData.Record(s); record.put("aUnion", 99); result = unionTester(s, record); assertTrue(result.value instanceof Integer); assertEquals(99, result.value); uoi = (UnionObjectInspector)result.oi; assertEquals(0, uoi.getTag(result.unionObject)); } @Test public void canDeserializeEvolvedUnions1() throws SerDeException, IOException { Schema ws = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.UNION_SCHEMA); Schema rs = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.UNION_SCHEMA_2); GenericData.Record record = new GenericData.Record(ws); record.put("aUnion", "this is a string"); ResultPair result = unionTester(ws, rs, record); assertTrue(result.value instanceof String); assertEquals("this is a string", result.value); UnionObjectInspector uoi = (UnionObjectInspector)result.oi; // The null in union type should be removed assertEquals(1, uoi.getTag(result.unionObject)); // Now the other enum possibility record = new GenericData.Record(ws); record.put("aUnion", 99); result = unionTester(ws, rs, record); assertTrue(result.value instanceof Integer); assertEquals(99, result.value); uoi = (UnionObjectInspector)result.oi; // The null in union type should be removed assertEquals(0, uoi.getTag(result.unionObject)); } @Test public void canDeserializeEvolvedUnions2() throws SerDeException, IOException { Schema ws = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.UNION_SCHEMA_3); Schema rs = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.UNION_SCHEMA_4); GenericData.Record record = new GenericData.Record(ws); record.put("aUnion", 90); ResultPair result = unionTester(ws, rs, record); assertTrue(result.value instanceof Integer); assertEquals(90, result.value); UnionObjectInspector uoi = (UnionObjectInspector)result.oi; assertEquals(0, uoi.getTag(result.unionObject)); // Now the other enum possibility record = new GenericData.Record(ws); record.put("aUnion", 99.9f); result = unionTester(ws, rs, record); assertTrue(result.value instanceof Float); assertEquals(99.9f, result.value); uoi = (UnionObjectInspector)result.oi; assertEquals(1, uoi.getTag(result.unionObject)); } private ResultPair unionTester(Schema ws, GenericData.Record record) throws SerDeException, IOException { return unionTester(ws, ws, record); } private ResultPair unionTester(Schema ws, Schema rs, GenericData.Record record) throws SerDeException, IOException { assertTrue(GENERIC_DATA.validate(ws, record)); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(rs); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, rs); assertEquals(1, row.size()); StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); List<? extends StructField> fieldRefs = oi.getAllStructFieldRefs(); assertEquals(1, fieldRefs.size()); StructField fieldRef = fieldRefs.get(0); assertEquals("aunion", fieldRef.getFieldName()); Object theUnion = oi.getStructFieldData(row, fieldRef); assertTrue(fieldRef.getFieldObjectInspector() instanceof UnionObjectInspector); UnionObjectInspector fieldObjectInspector = (UnionObjectInspector)fieldRef.getFieldObjectInspector(); Object value = fieldObjectInspector.getField(theUnion); return new ResultPair(fieldObjectInspector, value, theUnion); } @Test // Enums are one of two types we fudge for Hive. Enums go in, Strings come out. public void canDeserializeEnums() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.ENUM_SCHEMA); GenericData.Record record = new GenericData.Record(s); record.put("baddies", new GenericData.EnumSymbol(s.getField("baddies").schema(),"DALEKS")); assertTrue(GENERIC_DATA.validate(s, record)); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); List<? extends StructField> fieldRefs = oi.getAllStructFieldRefs(); assertEquals(1, fieldRefs.size()); StructField fieldRef = fieldRefs.get(0); assertEquals("baddies", fieldRef.getFieldName()); Object theStringObject = oi.getStructFieldData(row, fieldRef); assertTrue(fieldRef.getFieldObjectInspector() instanceof StringObjectInspector); StringObjectInspector soi = (StringObjectInspector)fieldRef.getFieldObjectInspector(); String finalValue = soi.getPrimitiveJavaObject(theStringObject); assertEquals("DALEKS", finalValue); } @Test // Fixed doesn't exist in Hive. Fixeds go in, lists of bytes go out. public void canDeserializeFixed() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.FIXED_SCHEMA); GenericData.Record record = new GenericData.Record(s); byte [] bytes = "ANANCIENTBLUEBOX".getBytes(); record.put("hash", new GenericData.Fixed(s, bytes)); assertTrue(GENERIC_DATA.validate(s, record)); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); Object byteObject = row.get(0); assertTrue(byteObject instanceof byte[]); byte[] outBytes = (byte[]) byteObject; // Verify the raw object that's been created for(int i = 0; i < bytes.length; i++) { assertEquals(bytes[i], outBytes[i]); } // Now go the correct way, through objectinspectors StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); List<Object> fieldsDataAsList = oi.getStructFieldsDataAsList(row); assertEquals(1, fieldsDataAsList.size()); StructField fieldRef = oi.getStructFieldRef("hash"); outBytes = (byte[]) oi.getStructFieldData(row, fieldRef); for(int i = 0; i < outBytes.length; i++) { assertEquals(bytes[i], outBytes[i]); } } @Test public void canDeserializeBytes() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.BYTES_SCHEMA); GenericData.Record record = new GenericData.Record(s); byte [] bytes = "ANANCIENTBLUEBOX".getBytes(); ByteBuffer bb = ByteBuffer.wrap(bytes); bb.rewind(); record.put("bytesField", bb); assertTrue(GENERIC_DATA.validate(s, record)); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); Object byteObject = row.get(0); assertTrue(byteObject instanceof byte[]); byte[] outBytes = (byte[]) byteObject; // Verify the raw object that's been created for(int i = 0; i < bytes.length; i++) { assertEquals(bytes[i], outBytes[i]); } // Now go the correct way, through objectinspectors StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); List<Object> fieldsDataAsList = oi.getStructFieldsDataAsList(row); assertEquals(1, fieldsDataAsList.size()); StructField fieldRef = oi.getStructFieldRef("bytesField"); outBytes = (byte[]) oi.getStructFieldData(row, fieldRef); for(int i = 0; i < outBytes.length; i++) { assertEquals(bytes[i], outBytes[i]); } } @Test public void canDeserializeNullableTypes() throws IOException, SerDeException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.NULLABLE_STRING_SCHEMA); GenericData.Record record = new GenericData.Record(s); record.put("nullableString", "this is a string"); verifyNullableType(record, s, "nullableString", "this is a string"); record = new GenericData.Record(s); record.put("nullableString", null); verifyNullableType(record, s, "nullableString", null); } @Test public void canDeserializeNullableEnums() throws IOException, SerDeException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.NULLABLE_ENUM_SCHEMA); GenericData.Record record = new GenericData.Record(s); record.put("nullableEnum", new GenericData.EnumSymbol(AvroSerdeUtils.getOtherTypeFromNullableType(s.getField("nullableEnum").schema()), "CYBERMEN")); verifyNullableType(record, s, "nullableEnum", "CYBERMEN"); record = new GenericData.Record(s); record.put("nullableEnum", null); verifyNullableType(record, s, "nullableEnum", null); } @Test public void canDeserializeMapWithNullablePrimitiveValues() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator .MAP_WITH_NULLABLE_PRIMITIVE_VALUE_TYPE_SCHEMA); GenericData.Record record = new GenericData.Record(s); Map<String, Long> m = new HashMap<String, Long>(); m.put("one", 1l); m.put("two", 2l); m.put("three", 3l); m.put("mu", null); record.put("aMap", m); assertTrue(GENERIC_DATA.validate(s, record)); System.out.println("record = " + record); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); Object theMapObject = row.get(0); assertTrue(theMapObject instanceof Map); Map theMap = (Map)theMapObject; // Verify the raw object that's been created assertEquals(1l, theMap.get("one")); assertEquals(2l, theMap.get("two")); assertEquals(3l, theMap.get("three")); assertTrue(theMap.containsKey("mu")); assertEquals(null, theMap.get("mu")); // Verify that the provided object inspector can pull out these same values StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); List<Object> z = oi.getStructFieldsDataAsList(row); assertEquals(1, z.size()); StructField fieldRef = oi.getStructFieldRef("amap"); Map theMap2 = (Map)oi.getStructFieldData(row, fieldRef); assertEquals(1l, theMap2.get("one")); assertEquals(2l, theMap2.get("two")); assertEquals(3l, theMap2.get("three")); assertTrue(theMap2.containsKey("mu")); assertEquals(null, theMap2.get("mu")); } @Test public void canDeserializeMapsWithJavaLangStringKeys() throws IOException, SerDeException { // Ensures maps can be deserialized when avro.java.string=String. // See http://stackoverflow.com/a/19868919/312944 for why that might be used. String schemaString = "{\n" + " \"namespace\": \"testing\",\n" + " \"name\": \"oneMap\",\n" + " \"type\": \"record\",\n" + " \"fields\": [\n" + " {\n" + " \"name\":\"aMap\",\n" + " \"type\":{\"type\":\"map\",\n" + " \"avro.java.string\":\"String\",\n" + " \"values\":\"long\"}\n" + "\t}\n" + " ]\n" + "}"; Schema s = AvroSerdeUtils.getSchemaFor(schemaString); GenericData.Record record = new GenericData.Record(s); Map<String, Long> m = new Hashtable<String, Long>(); m.put("one", 1l); m.put("two", 2l); m.put("three", 3l); record.put("aMap", m); assertTrue(GENERIC_DATA.validate(s, record)); System.out.println("record = " + record); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); Object theMapObject = row.get(0); assertTrue(theMapObject instanceof Map); Map theMap = (Map)theMapObject; // Verify the raw object that's been created assertEquals(1l, theMap.get("one")); assertEquals(2l, theMap.get("two")); assertEquals(3l, theMap.get("three")); // Verify that the provided object inspector can pull out these same values StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); List<Object> z = oi.getStructFieldsDataAsList(row); assertEquals(1, z.size()); StructField fieldRef = oi.getStructFieldRef("amap"); Map theMap2 = (Map)oi.getStructFieldData(row, fieldRef); assertEquals(1l, theMap2.get("one")); assertEquals(2l, theMap2.get("two")); assertEquals(3l, theMap2.get("three")); } private void verifyNullableType(GenericData.Record record, Schema s, String fieldName, String expected) throws SerDeException, IOException { assertTrue(GENERIC_DATA.validate(s, record)); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, row.size()); Object rowElement = row.get(0); StandardStructObjectInspector oi = (StandardStructObjectInspector)aoig.getObjectInspector(); List<Object> fieldsDataAsList = oi.getStructFieldsDataAsList(row); assertEquals(1, fieldsDataAsList.size()); StructField fieldRef = oi.getStructFieldRef(fieldName); ObjectInspector fieldObjectInspector = fieldRef.getFieldObjectInspector(); StringObjectInspector soi = (StringObjectInspector)fieldObjectInspector; if(expected == null) { assertNull(soi.getPrimitiveJavaObject(rowElement)); } else { assertEquals(expected, soi.getPrimitiveJavaObject(rowElement)); } } @Test public void verifyCaching() throws SerDeException, IOException { Schema s = AvroSerdeUtils.getSchemaFor(TestAvroObjectInspectorGenerator.RECORD_SCHEMA); GenericData.Record record = new GenericData.Record(s); GenericData.Record innerRecord = new GenericData.Record(s.getField("aRecord").schema()); innerRecord.put("int1", 42); innerRecord.put("boolean1", true); innerRecord.put("long1", 42432234234l); record.put("aRecord", innerRecord); assertTrue(GENERIC_DATA.validate(s, record)); AvroGenericRecordWritable garw = Utils.serializeAndDeserializeRecord(record); UID recordReaderID = new UID(); garw.setRecordReaderID(recordReaderID); AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s); AvroDeserializer de = new AvroDeserializer(); ArrayList<Object> row = (ArrayList<Object>) de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); assertEquals(1, de.getNoEncodingNeeded().size()); assertEquals(0, de.getReEncoderCache().size()); // Read the record with the same record reader ID row = (ArrayList<Object>) de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); //Expecting not to change the size of internal structures assertEquals(1, de.getNoEncodingNeeded().size()); assertEquals(0, de.getReEncoderCache().size()); //Read the record with **different** record reader ID garw.setRecordReaderID(new UID()); //New record reader ID row = (ArrayList<Object>) de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, s); //Expecting to change the size of internal structures assertEquals(2, de.getNoEncodingNeeded().size()); assertEquals(0, de.getReEncoderCache().size()); //Read the record with **different** record reader ID and **evolved** schema Schema evolvedSchema = AvroSerdeUtils.getSchemaFor(s.toString()); evolvedSchema.getField("aRecord").schema().addProp("Testing", "meaningless"); garw.setRecordReaderID(recordReaderID = new UID()); //New record reader ID row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, evolvedSchema); //Expecting to change the size of internal structures assertEquals(2, de.getNoEncodingNeeded().size()); assertEquals(1, de.getReEncoderCache().size()); //Read the record with existing record reader ID and same **evolved** schema garw.setRecordReaderID(recordReaderID); //Reuse record reader ID row = (ArrayList<Object>)de.deserialize(aoig.getColumnNames(), aoig.getColumnTypes(), garw, evolvedSchema); //Expecting NOT to change the size of internal structures assertEquals(2, de.getNoEncodingNeeded().size()); assertEquals(1, de.getReEncoderCache().size()); } }