Author: scottcarey
Date: Mon Apr 18 23:12:23 2011
New Revision: 1094812

URL: http://svn.apache.org/viewvc?rev=1094812&view=rev
Log:
AVRO-790 Java: GenericDatumReader can fail when reusing objects with unions 
containing 'bytes' fields

Modified:
    avro/trunk/CHANGES.txt
    
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
    avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java

Modified: avro/trunk/CHANGES.txt
URL: 
http://svn.apache.org/viewvc/avro/trunk/CHANGES.txt?rev=1094812&r1=1094811&r2=1094812&view=diff
==============================================================================
--- avro/trunk/CHANGES.txt (original)
+++ avro/trunk/CHANGES.txt Mon Apr 18 23:12:23 2011
@@ -49,6 +49,9 @@ Avro 1.5.1 (unreleased)
     AVRO-780. Java: Fix a NullPointerException with reflect data when
     a union contains an array and null. (cutting)
 
+    AVRO-790. Java: GenericDatumReader can fail when reusing objects with 
unions
+    containing 'bytes' fields. (scottcarey)
+
 Avro 1.5.0 (10 March 2011)
 
   INCOMPATIBLE CHANGES

Modified: 
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java?rev=1094812&r1=1094811&r2=1094812&view=diff
==============================================================================
--- 
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
 (original)
+++ 
avro/trunk/lang/java/avro/src/main/java/org/apache/avro/generic/GenericDatumReader.java
 Mon Apr 18 23:12:23 2011
@@ -330,7 +330,7 @@ public class GenericDatumReader<D> imple
    * byte array representation.  By default, this calls {@link
    * Decoder#readBytes(ByteBuffer)}.*/
   protected Object readBytes(Object old, Decoder in) throws IOException {
-    return in.readBytes((ByteBuffer)old);
+    return in.readBytes(old instanceof ByteBuffer ? (ByteBuffer) old : null);
   }
 
   /** Called to read integers.  Subclasses may override to use a different

Modified: avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java
URL: 
http://svn.apache.org/viewvc/avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java?rev=1094812&r1=1094811&r2=1094812&view=diff
==============================================================================
--- avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java 
(original)
+++ avro/trunk/lang/java/ipc/src/test/java/org/apache/avro/TestSchema.java Mon 
Apr 18 23:12:23 2011
@@ -45,7 +45,6 @@ import org.apache.avro.io.DatumWriter;
 import org.apache.avro.io.Decoder;
 import org.apache.avro.io.Encoder;
 import org.apache.avro.io.EncoderFactory;
-import org.apache.avro.io.JsonDecoder;
 import org.apache.avro.compiler.specific.TestSpecificCompiler;
 import org.apache.avro.util.Utf8;
 
@@ -79,7 +78,7 @@ public class TestSchema {
       + "      \"name\": \"inner_union\" }\n" + "  ]\n" + "}\n";
 
   private static final int COUNT =
-    Integer.parseInt(System.getProperty("test.count", "10"));
+    Integer.parseInt(System.getProperty("test.count", "30"));
 
   @Test
   public void testNull() throws Exception {
@@ -163,6 +162,18 @@ public class TestSchema {
     check("{\"type\":\"map\", \"values\":\"long\"}", "{\"a\":1}", map);
     checkParseError("{\"type\":\"map\"}");        // values required
   }
+  
+  @Test
+  public void testUnionMap() throws Exception {
+    String unionMapSchema = "{\"name\":\"foo\", \"type\":\"record\"," +
+               " \"fields\":[ {\"name\":\"mymap\", \"type\":" +
+               "   [{\"type\":\"map\", \"values\":" +
+               "      [\"int\",\"long\",\"float\",\"string\"]}," +
+               "    \"null\"]" +
+               "   }]" +
+               " }";
+    check(unionMapSchema, true);
+  }
 
   @Test
   public void testRecord() throws Exception {
@@ -558,6 +569,7 @@ public class TestSchema {
     throws Exception {
     Schema schema = Schema.parse(jsonSchema);
     checkProp(schema);
+    Object reuse = null;
     for (Object datum : new RandomData(schema, COUNT)) {
 
       if (induce) {
@@ -570,7 +582,10 @@ public class TestSchema {
 
       checkBinary(schema, datum,
                   new GenericDatumWriter<Object>(),
-                  new GenericDatumReader<Object>());
+                  new GenericDatumReader<Object>(), null);
+      reuse = checkBinary(schema, datum,
+          new GenericDatumWriter<Object>(),
+          new GenericDatumReader<Object>(), reuse);
       checkDirectBinary(schema, datum,
                   new GenericDatumWriter<Object>(),
                   new GenericDatumReader<Object>());
@@ -603,6 +618,14 @@ public class TestSchema {
                                  DatumWriter<Object> writer,
                                  DatumReader<Object> reader)
     throws IOException {
+    checkBinary(schema, datum, writer, reader, null);
+  }
+  
+  public static Object checkBinary(Schema schema, Object datum,
+                                 DatumWriter<Object> writer,
+                                 DatumReader<Object> reader,
+                                 Object reuse)
+    throws IOException {
     ByteArrayOutputStream out = new ByteArrayOutputStream();
     writer.setSchema(schema);
     Encoder encoder = EncoderFactory.get().binaryEncoder(out, null);
@@ -613,10 +636,11 @@ public class TestSchema {
     reader.setSchema(schema);
         
     Object decoded =
-      reader.read(null, DecoderFactory.get().binaryDecoder(
+      reader.read(reuse, DecoderFactory.get().binaryDecoder(
           data, null));
       
     assertEquals("Decoded data does not match.", datum, decoded);
+    return decoded;
   }
 
   public static void checkDirectBinary(Schema schema, Object datum,


Reply via email to