Index: serde/ivy.xml
===================================================================
--- serde/ivy.xml (revision 1344913)
+++ serde/ivy.xml (working copy)
@@ -45,5 +45,9 @@
transitive="false"/>
+
+
Index: serde/src/test/org/apache/hadoop/hive/serde2/avro/Utils.java
===================================================================
--- serde/src/test/org/apache/hadoop/hive/serde2/avro/Utils.java (revision 0)
+++ serde/src/test/org/apache/hadoop/hive/serde2/avro/Utils.java (revision 0)
@@ -0,0 +1,45 @@
+/*
+ * 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 org.apache.avro.generic.GenericData;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+class Utils {
+ // Force Avro to serialize and de-serialize the record to make sure it has a
+ // chance to muck with the bytes and we're working against real Avro data.
+ public static AvroGenericRecordWritable
+ serializeAndDeserializeRecord(GenericData.Record record) throws IOException {
+ AvroGenericRecordWritable garw = new AvroGenericRecordWritable(record);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ DataOutputStream daos = new DataOutputStream(baos);
+ garw.write(daos);
+
+ ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
+ DataInputStream dais = new DataInputStream(bais);
+
+ AvroGenericRecordWritable garw2 = new AvroGenericRecordWritable();
+ garw2.readFields(dais);
+ return garw2;
+ }
+}
Index: serde/src/test/org/apache/hadoop/hive/serde2/avro/TestAvroSerializer.java
===================================================================
--- serde/src/test/org/apache/hadoop/hive/serde2/avro/TestAvroSerializer.java (revision 0)
+++ serde/src/test/org/apache/hadoop/hive/serde2/avro/TestAvroSerializer.java (revision 0)
@@ -0,0 +1,229 @@
+/*
+ * 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 org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+import org.apache.hadoop.hive.serde2.SerDeException;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
+import org.apache.hadoop.io.Writable;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class TestAvroSerializer {
+
+ private Schema buildSchema(String recordValues) {
+ String s = "{\n" +
+ " \"namespace\": \"org.apache.hadoop.hive\",\n" +
+ " \"name\": \"test_serializer\",\n" +
+ " \"type\": \"record\",\n" +
+ " \"fields\": [" +
+ recordValues +
+ " ] }";
+ return Schema.parse(s);
+ }
+
+ /**
+ * Verify that we can serialize an avro value by taking one, running it through
+ * the deser process and then serialize it again.
+ */
+ private GenericRecord serializeAndDeserialize(String recordValue,
+ String fieldName, Object fieldValue) throws SerDeException, IOException {
+ Schema s = buildSchema(recordValue);
+ GenericData.Record r = new GenericData.Record(s);
+ r.put(fieldName, fieldValue);
+
+ AvroSerializer as = new AvroSerializer();
+
+ AvroDeserializer ad = new AvroDeserializer();
+ AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s);
+ ObjectInspector oi = aoig.getObjectInspector();
+ List columnNames = aoig.getColumnNames();
+ List columnTypes = aoig.getColumnTypes();
+
+ AvroGenericRecordWritable agrw = Utils.serializeAndDeserializeRecord(r);
+ Object obj = ad.deserialize(columnNames, columnTypes, agrw, s);
+
+ Writable result = as.serialize(obj, oi, columnNames, columnTypes, s);
+ assertTrue(result instanceof AvroGenericRecordWritable);
+ GenericRecord r2 = ((AvroGenericRecordWritable) result).getRecord();
+ assertEquals(s, r2.getSchema());
+ return r2;
+ }
+
+ @Test
+ public void canSerializeStrings() throws SerDeException, IOException {
+ singleFieldTest("string1", "hello", "string");
+ }
+
+ private void singleFieldTest(String fieldName, Object fieldValue, String fieldType)
+ throws SerDeException, IOException {
+ GenericRecord r2 = serializeAndDeserialize("{ \"name\":\"" + fieldName +
+ "\", \"type\":\"" + fieldType + "\" }", fieldName, fieldValue);
+ assertEquals(fieldValue, r2.get(fieldName));
+ }
+
+ @Test
+ public void canSerializeInts() throws SerDeException, IOException {
+ singleFieldTest("int1", 42, "int");
+ }
+
+ @Test
+ public void canSerializeBooleans() throws SerDeException, IOException {
+ singleFieldTest("boolean1", true, "boolean");
+ }
+
+ @Test
+ public void canSerializeFloats() throws SerDeException, IOException {
+ singleFieldTest("float1", 42.24342f, "float");
+ }
+
+ @Test
+ public void canSerializeDoubles() throws SerDeException, IOException {
+ singleFieldTest("double1", 24.00000001, "double");
+ }
+
+ @Test
+ public void canSerializeLists() throws SerDeException, IOException {
+ List intList = new ArrayList();
+ Collections.addAll(intList, 1,2, 3);
+ String field = "{ \"name\":\"list1\", \"type\":{\"type\":\"array\", \"items\":\"int\"} }";
+ GenericRecord r = serializeAndDeserialize(field, "list1", intList);
+ assertEquals(intList, r.get("list1"));
+ }
+
+ @Test
+ public void canSerializeMaps() throws SerDeException, IOException {
+ Map m = new Hashtable();
+ m.put("yes", true);
+ m.put("no", false);
+ String field = "{ \"name\":\"map1\", \"type\":{\"type\":\"map\", \"values\":\"boolean\"} }";
+ GenericRecord r = serializeAndDeserialize(field, "map1", m);
+
+ assertEquals(m, r.get("map1"));
+ }
+
+ @Test
+ public void canSerializeStructs() throws SerDeException {
+ String field = "{ \"name\":\"struct1\", \"type\":{\"type\":\"record\", " +
+ "\"name\":\"struct1_name\", \"fields\": [\n" +
+ "{ \"name\":\"sInt\", \"type\":\"int\" }, { \"name\"" +
+ ":\"sBoolean\", \"type\":\"boolean\" }, { \"name\":\"sString\", \"type\":\"string\" } ] } }";
+
+ Schema s = buildSchema(field);
+ GenericData.Record innerRecord = new GenericData.Record(s.getField("struct1").schema());
+
+ innerRecord.put("sInt", 77);
+ innerRecord.put("sBoolean", false);
+ innerRecord.put("sString", "tedious");
+
+ GenericData.Record r = new GenericData.Record(s);
+ r.put("struct1", innerRecord);
+
+ AvroSerializer as = new AvroSerializer();
+
+ AvroDeserializer ad = new AvroDeserializer();
+ AvroObjectInspectorGenerator aoig = new AvroObjectInspectorGenerator(s);
+ ObjectInspector oi = aoig.getObjectInspector();
+ List columnNames = aoig.getColumnNames();
+ List columnTypes = aoig.getColumnTypes();
+ AvroGenericRecordWritable agrw = new AvroGenericRecordWritable(r);
+ Object obj = ad.deserialize(columnNames, columnTypes, agrw, s);
+
+ Writable result = as.serialize(obj, oi, columnNames, columnTypes, s);
+ assertTrue(result instanceof AvroGenericRecordWritable);
+ GenericRecord r2 = ((AvroGenericRecordWritable) result).getRecord();
+ assertEquals(s, r2.getSchema());
+
+ GenericRecord r3 = (GenericRecord)r2.get("struct1");
+ assertEquals(77, r3.get("sInt"));
+ assertEquals(false, r3.get("sBoolean"));
+ assertEquals("tedious", r3.get("sString"));
+ }
+
+ @Test
+ public void canSerializeUnions() throws SerDeException, IOException {
+ String field = "{ \"name\":\"union1\", \"type\":[\"float\", \"boolean\", \"string\"] }";
+ GenericRecord r = serializeAndDeserialize(field, "union1", 424.4f);
+ assertEquals(424.4f, r.get("union1"));
+
+ r = serializeAndDeserialize(field, "union1", true);
+ assertEquals(true, r.get("union1"));
+
+ r = serializeAndDeserialize(field, "union1", "hello");
+ assertEquals("hello", r.get("union1"));
+ }
+
+ private enum enum1 {BLUE, RED , GREEN};
+ @Test
+ public void canSerializeEnums() throws SerDeException, IOException {
+ for(enum1 e : enum1.values()) {
+ String field = "{ \"name\":\"enum1\", \"type\":{\"type\":\"enum\", " +
+ "\"name\":\"enum1_values\", \"symbols\":[\"BLUE\",\"RED\", \"GREEN\"]} }";
+ GenericRecord r = serializeAndDeserialize(field, "enum1", e);
+
+ assertEquals(e, enum1.valueOf(r.get("enum1").toString()));
+ }
+
+ }
+
+ @Test
+ public void canSerializeNullableTypes() throws SerDeException, IOException {
+ String field = "{ \"name\":\"nullableint\", \"type\":[\"int\", \"null\"] }";
+ GenericRecord r = serializeAndDeserialize(field, "nullableint", 42);
+ assertEquals(42, r.get("nullableint"));
+
+ r = serializeAndDeserialize(field, "nullableint", null);
+ assertNull(r.get("nullableint"));
+ }
+
+ @Test
+ public void canSerializeBytes() throws SerDeException, IOException {
+ String field = "{ \"name\":\"bytes1\", \"type\":\"bytes\" }";
+ ByteBuffer bb = ByteBuffer.wrap("easy as one two three".getBytes());
+ bb.rewind();
+ GenericRecord r = serializeAndDeserialize(field, "bytes1", bb);
+
+ assertEquals(bb, r.get("bytes1"));
+ }
+
+ @Test
+ public void canSerializeFixed() throws SerDeException, IOException {
+ String field = "{ \"name\":\"fixed1\", \"type\":{\"type\":\"fixed\", " +
+ "\"name\":\"threebytes\", \"size\":3} }";
+ GenericData.Fixed fixed = new GenericData.Fixed(buildSchema(field), "k9@".getBytes());
+ GenericRecord r = serializeAndDeserialize(field, "fixed1", fixed);
+
+ assertArrayEquals(fixed.bytes(), ((GenericData.Fixed) r.get("fixed1")).bytes());
+ }
+
+}
Index: serde/src/test/org/apache/hadoop/hive/serde2/avro/TestSchemaReEncoder.java
===================================================================
--- serde/src/test/org/apache/hadoop/hive/serde2/avro/TestSchemaReEncoder.java (revision 0)
+++ serde/src/test/org/apache/hadoop/hive/serde2/avro/TestSchemaReEncoder.java (revision 0)
@@ -0,0 +1,111 @@
+/*
+ * 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 org.apache.avro.Schema;
+import org.apache.avro.generic.GenericData;
+import org.apache.avro.generic.GenericRecord;
+import org.apache.hadoop.hive.serde2.SerDeException;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class TestSchemaReEncoder {
+ @Test
+ public void schemasCanAddFields() throws SerDeException {
+ String original = "{\n" +
+ " \"namespace\": \"org.apache.hadoop.hive\",\n" +
+ " \"name\": \"Line\",\n" +
+ " \"type\": \"record\",\n" +
+ " \"fields\": [\n" +
+ " {\n" +
+ " \"name\":\"text\",\n" +
+ " \"type\":\"string\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ String evolved = "{\n" +
+ " \"namespace\": \"org.apache.hadoop.hive\",\n" +
+ " \"name\": \"Line\",\n" +
+ " \"type\": \"record\",\n" +
+ " \"fields\": [\n" +
+ " {\n" +
+ " \"name\":\"text\",\n" +
+ " \"type\":\"string\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name\":\"new_kid\",\n" +
+ " \"type\":\"string\",\n" +
+ " \"default\":\"Hi!\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ Schema originalSchema = Schema.parse(original);
+ Schema evolvedSchema = Schema.parse(evolved);
+
+ GenericRecord record = new GenericData.Record(originalSchema);
+ record.put("text", "it is a far better thing I do, yadda, yadda");
+ assertTrue(GenericData.get().validate(originalSchema, record));
+ AvroDeserializer.SchemaReEncoder schemaReEncoder = new AvroDeserializer.SchemaReEncoder();
+ GenericRecord r2 = schemaReEncoder.reencode(record, evolvedSchema);
+
+ assertTrue(GenericData.get().validate(evolvedSchema, r2));
+ assertEquals("Hi!", r2.get("new_kid").toString());
+
+ // Now make sure that we can re-use the re-encoder against a completely
+ // different record to save resources
+ String original2 = "{\n" +
+ " \"namespace\": \"somebody.else\",\n" +
+ " \"name\": \"something_else\",\n" +
+ " \"type\": \"record\",\n" +
+ " \"fields\": [\n" +
+ " {\n" +
+ " \"name\":\"a\",\n" +
+ " \"type\":\"int\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ String evolved2 = "{\n" +
+ " \"namespace\": \"somebody.else\",\n" +
+ " \"name\": \"something_else\",\n" +
+ " \"type\": \"record\",\n" +
+ " \"fields\": [\n" +
+ " {\n" +
+ " \"name\":\"a\",\n" +
+ " \"type\":\"int\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name\":\"b\",\n" +
+ " \"type\":\"long\",\n" +
+ " \"default\":42\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ Schema originalSchema2 = Schema.parse(original2);
+ Schema evolvedSchema2 = Schema.parse(evolved2);
+
+ record = new GenericData.Record(originalSchema2);
+ record.put("a", 19);
+ assertTrue(GenericData.get().validate(originalSchema2, record));
+
+ r2 = schemaReEncoder.reencode(record, evolvedSchema2);
+ assertTrue(GenericData.get().validate(evolvedSchema2, r2));
+ assertEquals(42l, r2.get("b"));
+ }
+}
Index: serde/src/test/org/apache/hadoop/hive/serde2/avro/TestInstanceCache.java
===================================================================
--- serde/src/test/org/apache/hadoop/hive/serde2/avro/TestInstanceCache.java (revision 0)
+++ serde/src/test/org/apache/hadoop/hive/serde2/avro/TestInstanceCache.java (revision 0)
@@ -0,0 +1,78 @@
+/*
+ * 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 org.junit.Test;
+
+import static org.junit.Assert.assertSame;
+
+public class TestInstanceCache {
+ private static class Foo {
+ @Override
+ public int hashCode() {
+ return 42;
+ }
+ }
+
+ private static class Wrapper {
+ public final T wrapped;
+
+ private Wrapper(T wrapped) {
+ this.wrapped = wrapped;
+ }
+ }
+
+ @Test
+ public void instanceCachesOnlyCreateOneInstance() throws AvroSerdeException {
+ InstanceCache> ic = new InstanceCache>() {
+ @Override
+ protected Wrapper makeInstance(Foo hv) {
+ return new Wrapper(hv);
+ }
+ };
+ Foo f1 = new Foo();
+
+ Wrapper fc = ic.retrieve(f1);
+ assertSame(f1, fc.wrapped); // Our original foo should be in the wrapper
+
+ Foo f2 = new Foo(); // Different instance, same value
+
+ Wrapper fc2 = ic.retrieve(f2);
+ assertSame(fc2,fc); // Since equiv f, should get back first container
+ assertSame(fc2.wrapped, f1);
+ }
+
+ @Test
+ public void instanceCacheReturnsCorrectInstances() throws AvroSerdeException {
+ InstanceCache> ic = new InstanceCache>() {
+ @Override
+ protected Wrapper makeInstance(String hv) {
+ return new Wrapper(hv);
+ }
+ };
+
+ Wrapper one = ic.retrieve("one");
+ Wrapper two = ic.retrieve("two");
+
+ Wrapper anotherOne = ic.retrieve("one");
+ assertSame(one, anotherOne);
+
+ Wrapper anotherTwo = ic.retrieve("two");
+ assertSame(two, anotherTwo);
+ }
+}
Index: serde/src/test/org/apache/hadoop/hive/serde2/avro/TestAvroSerde.java
===================================================================
--- serde/src/test/org/apache/hadoop/hive/serde2/avro/TestAvroSerde.java (revision 0)
+++ serde/src/test/org/apache/hadoop/hive/serde2/avro/TestAvroSerde.java (revision 0)
@@ -0,0 +1,167 @@
+/*
+ * 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 org.apache.avro.Schema;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hive.serde2.SerDeException;
+import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.StandardStructObjectInspector;
+import org.apache.hadoop.hive.serde2.objectinspector.StructField;
+import org.apache.hadoop.io.Writable;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.List;
+import java.util.Properties;
+
+import static org.apache.hadoop.hive.serde2.avro.AvroSerdeUtils.AVRO_SERDE_SCHEMA;
+import static org.apache.hadoop.hive.serde2.avro.AvroSerdeUtils.SCHEMA_LITERAL;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+public class TestAvroSerde {
+ static final String originalSchemaString = "{\n" +
+ " \"namespace\": \"org.apache.hadoop.hive\",\n" +
+ " \"name\": \"previous\",\n" +
+ " \"type\": \"record\",\n" +
+ " \"fields\": [\n" +
+ " {\n" +
+ " \"name\":\"text\",\n" +
+ " \"type\":\"string\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+ static final String newSchemaString = "{\n" +
+ " \"namespace\": \"org.apache.hadoop.hive\",\n" +
+ " \"name\": \"new\",\n" +
+ " \"type\": \"record\",\n" +
+ " \"fields\": [\n" +
+ " {\n" +
+ " \"name\":\"text\",\n" +
+ " \"type\":\"string\"\n" +
+ " }\n" +
+ " ]\n" +
+ "}";
+
+ static final Schema originalSchema = Schema.parse(originalSchemaString);
+ static final Schema newSchema = Schema.parse(newSchemaString);
+
+ @Test
+ public void initializeDoesNotReuseSchemasFromConf() throws SerDeException {
+ // Hive will re-use the Configuration object that it passes in to be
+ // initialized. Therefore we need to make sure we don't look for any
+ // old schemas within it.
+ Configuration conf = new Configuration();
+ conf.set(AVRO_SERDE_SCHEMA, originalSchema.toString(false));
+
+ Properties props = new Properties();
+ props.put(SCHEMA_LITERAL, newSchemaString);
+
+
+ AvroSerDe asd = new AvroSerDe();
+ asd.initialize(conf, props);
+
+ // Verify that the schema now within the configuration is the one passed
+ // in via the properties
+ assertEquals(newSchema, Schema.parse(conf.get(AVRO_SERDE_SCHEMA)));
+ }
+
+ @Test
+ public void noSchemaProvidedReturnsErrorSchema() throws SerDeException {
+ Properties props = new Properties();
+
+ verifyErrorSchemaReturned(props);
+ }
+
+ @Test
+ public void gibberishSchemaProvidedReturnsErrorSchema() throws SerDeException {
+ Properties props = new Properties();
+ props.put(AvroSerdeUtils.SCHEMA_LITERAL, "blahblahblah");
+
+ verifyErrorSchemaReturned(props);
+ }
+
+ @Test
+ public void emptySchemaProvidedReturnsErrorSchema() throws SerDeException {
+ Properties props = new Properties();
+ props.put(AvroSerdeUtils.SCHEMA_LITERAL, "");
+
+ verifyErrorSchemaReturned(props);
+ }
+
+ @Test
+ public void badSchemaURLProvidedReturnsErrorSchema() throws SerDeException {
+ Properties props = new Properties();
+ props.put(AvroSerdeUtils.SCHEMA_URL, "not://a/url");
+
+ verifyErrorSchemaReturned(props);
+ }
+
+ @Test
+ public void emptySchemaURLProvidedReturnsErrorSchema() throws SerDeException {
+ Properties props = new Properties();
+ props.put(AvroSerdeUtils.SCHEMA_URL, "");
+
+ verifyErrorSchemaReturned(props);
+ }
+
+ @Test
+ public void bothPropertiesSetToNoneReturnsErrorSchema() throws SerDeException {
+ Properties props = new Properties();
+ props.put(AvroSerdeUtils.SCHEMA_URL, AvroSerdeUtils.SCHEMA_NONE);
+ props.put(AvroSerdeUtils.SCHEMA_LITERAL, AvroSerdeUtils.SCHEMA_NONE);
+
+ verifyErrorSchemaReturned(props);
+ }
+
+ private void verifyErrorSchemaReturned(Properties props) throws SerDeException {
+ AvroSerDe asd = new AvroSerDe();
+ asd.initialize(new Configuration(), props);
+ assertTrue(asd.getObjectInspector() instanceof StandardStructObjectInspector);
+ StandardStructObjectInspector oi = (StandardStructObjectInspector)asd.getObjectInspector();
+ List extends StructField> allStructFieldRefs = oi.getAllStructFieldRefs();
+ assertEquals(SchemaResolutionProblem.SIGNAL_BAD_SCHEMA.getFields().size(), allStructFieldRefs.size());
+ StructField firstField = allStructFieldRefs.get(0);
+ assertTrue(firstField.toString().contains("error_error_error_error_error_error_error"));
+
+ try {
+ Writable mock = Mockito.mock(Writable.class);
+ asd.deserialize(mock);
+ fail("Should have thrown a BadSchemaException");
+ } catch (BadSchemaException bse) {
+ // good
+ }
+
+ try {
+ Object o = Mockito.mock(Object.class);
+ ObjectInspector mockOI = Mockito.mock(ObjectInspector.class);
+ asd.serialize(o, mockOI);
+ fail("Should have thrown a BadSchemaException");
+ } catch (BadSchemaException bse) {
+ // good
+ }
+ }
+
+ @Test
+ public void getSerializedClassReturnsCorrectType() {
+ AvroSerDe asd = new AvroSerDe();
+ assertEquals(AvroGenericRecordWritable.class, asd.getSerializedClass());
+ }
+}
Index: serde/src/test/org/apache/hadoop/hive/serde2/avro/TestAvroDeserializer.java
===================================================================
--- serde/src/test/org/apache/hadoop/hive/serde2/avro/TestAvroDeserializer.java (revision 0)
+++ serde/src/test/org/apache/hadoop/hive/serde2/avro/TestAvroDeserializer.java (revision 0)
@@ -0,0 +1,432 @@
+/*
+ * 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 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;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+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 = Schema.parse(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