avro-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ph...@apache.org
Subject svn commit: r905531 - in /hadoop/avro/trunk: CHANGES.txt lang/java/src/java/org/apache/avro/Schema.java lang/java/src/test/java/org/apache/avro/TestSchema.java
Date Tue, 02 Feb 2010 06:52:17 GMT
Author: philz
Date: Tue Feb  2 06:52:02 2010
New Revision: 905531

URL: http://svn.apache.org/viewvc?rev=905531&view=rev
Log:
AVRO-361. Specific Compiler fails to handle union with two fixed branches
(Scott Carey via philz)


Modified:
    hadoop/avro/trunk/CHANGES.txt
    hadoop/avro/trunk/lang/java/src/java/org/apache/avro/Schema.java
    hadoop/avro/trunk/lang/java/src/test/java/org/apache/avro/TestSchema.java

Modified: hadoop/avro/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/CHANGES.txt?rev=905531&r1=905530&r2=905531&view=diff
==============================================================================
--- hadoop/avro/trunk/CHANGES.txt (original)
+++ hadoop/avro/trunk/CHANGES.txt Tue Feb  2 06:52:02 2010
@@ -407,6 +407,8 @@
 
     AVRO-390. ResolvingDecoder does not handle default values for records well (thiru)
 
+    AVRO-361. Specific Compiler fails to handle union with two fixed branches (Scott Carey
via philz)
+
 Avro 1.2.0 (14 October 2009)
 
   INCOMPATIBLE CHANGES

Modified: hadoop/avro/trunk/lang/java/src/java/org/apache/avro/Schema.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/java/src/java/org/apache/avro/Schema.java?rev=905531&r1=905530&r2=905531&view=diff
==============================================================================
--- hadoop/avro/trunk/lang/java/src/java/org/apache/avro/Schema.java (original)
+++ hadoop/avro/trunk/lang/java/src/java/org/apache/avro/Schema.java Tue Feb  2 06:52:02 2010
@@ -610,13 +610,24 @@
       super(Type.UNION);
       this.types = types;
       int seen = 0;
+      Set<String> seenNames = new HashSet<String>();
       for (Schema type : types) {                 // check legality of union
         switch (type.getType()) {
         case UNION: 
           throw new AvroRuntimeException("Nested union: "+this);
         case RECORD:
-          if (type.getName() != null)
-            continue;
+        case FIXED:
+        case ENUM:
+          String fullname = type.getFullName();
+          if (fullname != null) {
+            if (seenNames.add(fullname)) {
+              continue;
+            } else {
+              throw new AvroRuntimeException("Duplicate name in union:" + fullname);
+            }
+          } else {
+            throw new AvroRuntimeException("Nameless Record, Fixed, or Enum in union:"+this);
+          }
         default:
           int mask = 1 << type.getType().ordinal();
           if ((seen & mask) != 0)

Modified: hadoop/avro/trunk/lang/java/src/test/java/org/apache/avro/TestSchema.java
URL: http://svn.apache.org/viewvc/hadoop/avro/trunk/lang/java/src/test/java/org/apache/avro/TestSchema.java?rev=905531&r1=905530&r2=905531&view=diff
==============================================================================
--- hadoop/avro/trunk/lang/java/src/test/java/org/apache/avro/TestSchema.java (original)
+++ hadoop/avro/trunk/lang/java/src/test/java/org/apache/avro/TestSchema.java Tue Feb  2 06:52:02
2010
@@ -27,7 +27,10 @@
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.List;
 
 import org.apache.avro.Schema.Type;
 import org.apache.avro.generic.GenericArray;
@@ -233,6 +236,61 @@
   }
 
   @Test
+  public void testComplexUnions() throws Exception {
+    // one of each unnamed type and two of named types
+    String partial = "[\"int\", \"long\", \"float\", \"double\", \"boolean\", \"bytes\","
+
+    " \"string\", {\"type\":\"array\", \"items\": \"long\"}," +
+    " {\"type\":\"map\", \"values\":\"long\"}";
+    String namedTypes = ", {\"type\":\"record\",\"name\":\"Foo\",\"fields\":[]}," +
+    " {\"type\":\"fixed\",\"name\":\"Bar\",\"size\": 1}," +
+    " {\"type\":\"enum\",\"name\":\"Baz\",\"symbols\": [\"X\"]}";
+    
+    String namedTypes2 = ", {\"type\":\"record\",\"name\":\"Foo2\",\"fields\":[]}," +
+    " {\"type\":\"fixed\",\"name\":\"Bar2\",\"size\": 1}," +
+    " {\"type\":\"enum\",\"name\":\"Baz2\",\"symbols\": [\"X\"]}";
+    
+    check(partial + namedTypes + "]", false);
+    check(partial + namedTypes + namedTypes2 + "]", false); 
+    checkParseError(partial + namedTypes + namedTypes + "]");
+    
+    // fail with two branches of the same unnamed type
+    checkUnionError(new Schema[] {Schema.create(Type.INT), Schema.create(Type.INT)});
+    checkUnionError(new Schema[] {Schema.create(Type.LONG), Schema.create(Type.LONG)});
+    checkUnionError(new Schema[] {Schema.create(Type.FLOAT), Schema.create(Type.FLOAT)});
+    checkUnionError(new Schema[] {Schema.create(Type.DOUBLE), Schema.create(Type.DOUBLE)});
+    checkUnionError(new Schema[] {Schema.create(Type.BOOLEAN), Schema.create(Type.BOOLEAN)});
+    checkUnionError(new Schema[] {Schema.create(Type.BYTES), Schema.create(Type.BYTES)});
+    checkUnionError(new Schema[] {Schema.create(Type.STRING), Schema.create(Type.STRING)});
+    checkUnionError(new Schema[] {Schema.createArray(Schema.create(Type.INT)), 
+        Schema.createArray(Schema.create(Type.INT))});
+    checkUnionError(new Schema[] {Schema.createMap(Schema.create(Type.INT)), 
+        Schema.createMap(Schema.create(Type.INT))});
+    
+    List<String> symbols = new ArrayList<String>();
+    symbols.add("NOTHING");
+    
+    // succeed with two branches of the same named type, if different names
+    buildUnion(new Schema[] {Schema.createRecord("Foo", null, "org.test", false),
+        Schema.createRecord("Foo2", null, "org.test", false)});
+    buildUnion(new Schema[] {Schema.createEnum("Bar", null, "org.test", symbols),
+        Schema.createEnum("Bar2", null, "org.test", symbols)});
+    buildUnion(new Schema[] {Schema.createFixed("Baz", null, "org.test", 2),
+        Schema.createFixed("Baz2", null, "org.test", 1)});
+
+    // fail with two branches of the same named type, but same names
+    checkUnionError(new Schema[] {Schema.createRecord("Foo", null, "org.test", false),
+        Schema.createRecord("Foo", null, "org.test", false)});
+    checkUnionError(new Schema[] {Schema.createEnum("Bar", null, "org.test", symbols),
+        Schema.createEnum("Bar", null, "org.test", symbols)});
+    checkUnionError(new Schema[] {Schema.createFixed("Baz", null, "org.test", 2),
+        Schema.createFixed("Baz", null, "org.test", 1)});
+    
+    Schema union = buildUnion(new Schema[] {Schema.create(Type.INT)});
+    // fail if creating a union of a union
+    checkUnionError(new Schema[] {union});
+  }
+  
+  @Test
   public void testComplexProp() throws Exception {
     String json = "{\"type\":\"null\", \"foo\": [0]}";
     Schema s = Schema.parse(json);
@@ -270,6 +328,21 @@
     fail("Should not have parsed: "+json);
   }
 
+  private static void checkUnionError(Schema[] branches) {
+    List<Schema> branchList = Arrays.asList(branches);
+    try {
+      Schema.createUnion(branchList);
+      fail("Union should not have constructed from: " + branchList);
+    } catch (AvroRuntimeException are) {
+      return;
+    }
+  }
+
+  private static Schema buildUnion(Schema[] branches) {
+    List<Schema> branchList = Arrays.asList(branches);
+    return Schema.createUnion(branchList);
+  }
+
   /**
    * Makes sure that "doc" tags are transcribed in the schemas.
    * Note that there are docs both for fields and for the records



Mime
View raw message