blob: 58a1a6f5493adf246943eb3d5d1249b465747408 [file] [log] [blame]
/**
* 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.avro;
import java.io.File;
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 java.util.Map;
import org.apache.avro.Schema.Field.Order;
import org.apache.avro.file.DataFileReader;
import org.apache.avro.file.DataFileWriter;
import org.apache.avro.generic.GenericData;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.generic.GenericDatumWriter;
import org.apache.avro.generic.GenericRecordBuilder;
import org.codehaus.jackson.node.NullNode;
import org.junit.Assert;
import org.junit.Test;
public class TestSchemaBuilder {
private static final File DIR = new File(System.getProperty("test.dir", "/tmp"));
private static final File FILE = new File(DIR, "test.avro");
@Test
public void testRecord() {
Schema schema = SchemaBuilder
.record("myrecord").namespace("org.example").aliases("oldrecord").fields()
.name("f0").aliases("f0alias").type().stringType().noDefault()
.name("f1").doc("This is f1").type().longType().noDefault()
.name("f2").type().nullable().booleanType().booleanDefault(true)
.endRecord();
Assert.assertEquals("myrecord", schema.getName());
Assert.assertEquals("org.example", schema.getNamespace());
Assert.assertEquals("org.example.oldrecord", schema.getAliases().iterator().next());
Assert.assertFalse(schema.isError());
List<Schema.Field> fields = schema.getFields();
Assert.assertEquals(3, fields.size());
Assert.assertEquals(
new Schema.Field("f0", Schema.create(Schema.Type.STRING), null, null),
fields.get(0));
Assert.assertTrue(fields.get(0).aliases().contains("f0alias"));
Assert.assertEquals(
new Schema.Field("f1", Schema.create(Schema.Type.LONG), "This is f1", null),
fields.get(1));
List<Schema> types = new ArrayList<Schema>();
types.add(Schema.create(Schema.Type.BOOLEAN));
types.add(Schema.create(Schema.Type.NULL));
Schema optional = Schema.createUnion(types);
Assert.assertEquals(new Schema.Field("f2", optional, null, true),
fields.get(2));
}
@Test
public void testDoc() {
Schema s = SchemaBuilder.fixed("myfixed").doc("mydoc").size(1);
Assert.assertEquals("mydoc", s.getDoc());
}
@Test
public void testProps() {
Schema s = SchemaBuilder.builder().intBuilder()
.prop("p1", "v1")
.prop("p2", "v2")
.prop("p2", "v2real") // overwrite
.endInt();
@SuppressWarnings("deprecation")
int size = s.getProps().size();
Assert.assertEquals(2, size);
Assert.assertEquals("v1", s.getProp("p1"));
Assert.assertEquals("v2real", s.getProp("p2"));
}
@Test
public void testNamespaces() {
Schema s1 = SchemaBuilder.record("myrecord")
.namespace("org.example")
.fields()
.name("myint").type().intType().noDefault()
.endRecord();
Schema s2 = SchemaBuilder.record("org.example.myrecord")
.fields()
.name("myint").type().intType().noDefault()
.endRecord();
Schema s3 = SchemaBuilder.record("org.example.myrecord")
.namespace("org.example2")
.fields()
.name("myint").type().intType().noDefault()
.endRecord();
Schema s4 = SchemaBuilder.builder("org.example").record("myrecord")
.fields()
.name("myint").type().intType().noDefault()
.endRecord();
Assert.assertEquals("myrecord", s1.getName());
Assert.assertEquals("myrecord", s2.getName());
Assert.assertEquals("myrecord", s3.getName());
Assert.assertEquals("myrecord", s4.getName());
Assert.assertEquals("org.example", s1.getNamespace());
Assert.assertEquals("org.example", s2.getNamespace());
Assert.assertEquals("org.example", s3.getNamespace()); // namespace call is ignored
Assert.assertEquals("org.example", s4.getNamespace());
Assert.assertEquals("org.example.myrecord", s1.getFullName());
Assert.assertEquals("org.example.myrecord", s2.getFullName());
Assert.assertEquals("org.example.myrecord", s3.getFullName());
Assert.assertEquals("org.example.myrecord", s4.getFullName());
}
@Test(expected = NullPointerException.class)
public void testMissingRecordName() {
SchemaBuilder
.record(null).fields() // null name
.name("f0").type().stringType().noDefault()
.endRecord();
}
@Test
public void testBoolean() {
Schema.Type type = Schema.Type.BOOLEAN;
Schema simple = SchemaBuilder.builder().booleanType();
Schema expected = primitive(type, simple);
Schema built1 = SchemaBuilder.builder()
.booleanBuilder().prop("p", "v").endBoolean();
Assert.assertEquals(expected, built1);
}
@Test
public void testInt() {
Schema.Type type = Schema.Type.INT;
Schema simple = SchemaBuilder.builder().intType();
Schema expected = primitive(type, simple);
Schema built1 = SchemaBuilder.builder()
.intBuilder().prop("p", "v").endInt();
Assert.assertEquals(expected, built1);
}
@Test
public void testLong() {
Schema.Type type = Schema.Type.LONG;
Schema simple = SchemaBuilder.builder().longType();
Schema expected = primitive(type, simple);
Schema built1 = SchemaBuilder.builder()
.longBuilder().prop("p", "v").endLong();
Assert.assertEquals(expected, built1);
}
@Test
public void testFloat() {
Schema.Type type = Schema.Type.FLOAT;
Schema simple = SchemaBuilder.builder().floatType();
Schema expected = primitive(type, simple);
Schema built1 = SchemaBuilder.builder()
.floatBuilder().prop("p", "v").endFloat();
Assert.assertEquals(expected, built1);
}
@Test
public void testDuble() {
Schema.Type type = Schema.Type.DOUBLE;
Schema simple = SchemaBuilder.builder().doubleType();
Schema expected = primitive(type, simple);
Schema built1 = SchemaBuilder.builder()
.doubleBuilder().prop("p", "v").endDouble();
Assert.assertEquals(expected, built1);
}
@Test
public void testString() {
Schema.Type type = Schema.Type.STRING;
Schema simple = SchemaBuilder.builder().stringType();
Schema expected = primitive(type, simple);
Schema built1 = SchemaBuilder.builder()
.stringBuilder().prop("p", "v").endString();
Assert.assertEquals(expected, built1);
}
@Test
public void testBytes() {
Schema.Type type = Schema.Type.BYTES;
Schema simple = SchemaBuilder.builder().bytesType();
Schema expected = primitive(type, simple);
Schema built1 = SchemaBuilder.builder()
.bytesBuilder().prop("p", "v").endBytes();
Assert.assertEquals(expected, built1);
}
@Test
public void testNull() {
Schema.Type type = Schema.Type.NULL;
Schema simple = SchemaBuilder.builder().nullType();
Schema expected = primitive(type, simple);
Schema built1 = SchemaBuilder.builder()
.nullBuilder().prop("p", "v").endNull();
Assert.assertEquals(expected, built1);
}
private Schema primitive(Schema.Type type, Schema bare) {
// test creation of bare schema by name
Schema bareByName = SchemaBuilder.builder().type(type.getName());
Assert.assertEquals(Schema.create(type), bareByName);
Assert.assertEquals(bareByName, bare);
// return a schema with custom prop set
Schema p = Schema.create(type);
p.addProp("p", "v");
return p;
}
// @Test
// public void testError() {
// Schema schema = SchemaBuilder
// .errorType("myerror")
// .requiredString("message")
// .build();
//
// Assert.assertEquals("myerror", schema.getName());
// Assert.assertTrue(schema.isError());
// }
@Test
public void testRecursiveRecord() {
Schema schema = SchemaBuilder.record("LongList").fields()
.name("value").type().longType().noDefault()
.name("next").type().optional().type("LongList")
.endRecord();
Assert.assertEquals("LongList", schema.getName());
List<Schema.Field> fields = schema.getFields();
Assert.assertEquals(2, fields.size());
Assert.assertEquals(
new Schema.Field("value", Schema.create(Schema.Type.LONG), null, null),
fields.get(0));
Assert.assertEquals(
Schema.Type.UNION,
fields.get(1).schema().getType());
Assert.assertEquals(
Schema.Type.NULL,
fields.get(1).schema().getTypes().get(0).getType());
Schema recordSchema = fields.get(1).schema().getTypes().get(1);
Assert.assertEquals(Schema.Type.RECORD, recordSchema.getType());
Assert.assertEquals("LongList", recordSchema.getName());
Assert.assertEquals(NullNode.getInstance(), fields.get(1).defaultValue());
}
@Test
public void testEnum() {
List<String> symbols = Arrays.asList("a", "b");
Schema expected = Schema.createEnum("myenum", null, null, symbols);
expected.addProp("p", "v");
Schema schema = SchemaBuilder.enumeration("myenum")
.prop("p", "v").symbols("a", "b");
Assert.assertEquals(expected, schema);
}
@Test
public void testFixed() {
Schema expected = Schema.createFixed("myfixed", null, null, 16);
expected.addAlias("myOldFixed");
Schema schema = SchemaBuilder.fixed("myfixed")
.aliases("myOldFixed").size(16);
Assert.assertEquals(expected, schema);
}
@Test
public void testArray() {
Schema longSchema = Schema.create(Schema.Type.LONG);
Schema expected = Schema.createArray(longSchema);
Schema schema1 = SchemaBuilder.array().items().longType();
Assert.assertEquals(expected, schema1);
Schema schema2 = SchemaBuilder.array().items(longSchema);
Assert.assertEquals(expected, schema2);
Schema schema3 = SchemaBuilder.array().prop("p", "v")
.items().type("long");
expected.addProp("p", "v");
Assert.assertEquals(expected, schema3);
}
@Test
public void testMap() {
Schema intSchema = Schema.create(Schema.Type.INT);
Schema expected = Schema.createMap(intSchema);
Schema schema1 = SchemaBuilder.map().values().intType();
Assert.assertEquals(expected, schema1);
Schema schema2 = SchemaBuilder.map().values(intSchema);
Assert.assertEquals(expected, schema2);
Schema schema3 = SchemaBuilder.map().prop("p", "v")
.values().type("int");
expected.addProp("p", "v");
Assert.assertEquals(expected, schema3);
}
@Test
public void testUnionAndNullable() {
List<Schema> types = new ArrayList<Schema>();
types.add(Schema.create(Schema.Type.LONG));
types.add(Schema.create(Schema.Type.NULL));
Schema expected = Schema.createUnion(types);
Schema schema = SchemaBuilder.unionOf()
.longType().and()
.nullType().endUnion();
Assert.assertEquals(expected, schema);
schema = SchemaBuilder.nullable().longType();
Assert.assertEquals(expected, schema);
}
@Test
public void testFields() {
Schema rec = SchemaBuilder.record("Rec").fields()
.name("documented").doc("documented").type().nullType().noDefault()
.name("ascending").orderAscending().type().booleanType().noDefault()
.name("descending").orderDescending().type().floatType().noDefault()
.name("ignored").orderIgnore().type().doubleType().noDefault()
.name("aliased").aliases("anAlias").type().stringType().noDefault()
.endRecord();
Assert.assertEquals("documented", rec.getField("documented").doc());
Assert.assertEquals(Order.ASCENDING, rec.getField("ascending").order());
Assert.assertEquals(Order.DESCENDING, rec.getField("descending").order());
Assert.assertEquals(Order.IGNORE, rec.getField("ignored").order());
Assert.assertTrue(rec.getField("aliased").aliases().contains("anAlias"));
}
@Test
public void testFieldShortcuts() {
Schema full = SchemaBuilder.record("Blah").fields()
.name("rbool").type().booleanType().noDefault()
.name("obool").type().optional().booleanType()
.name("nbool").type().nullable().booleanType().booleanDefault(true)
.name("rint").type().intType().noDefault()
.name("oint").type().optional().intType()
.name("nint").type().nullable().intType().intDefault(1)
.name("rlong").type().longType().noDefault()
.name("olong").type().optional().longType()
.name("nlong").type().nullable().longType().longDefault(2L)
.name("rfloat").type().floatType().noDefault()
.name("ofloat").type().optional().floatType()
.name("nfloat").type().nullable().floatType().floatDefault(-1.1f)
.name("rdouble").type().doubleType().noDefault()
.name("odouble").type().optional().doubleType()
.name("ndouble").type().nullable().doubleType().doubleDefault(99.9d)
.name("rstring").type().stringType().noDefault()
.name("ostring").type().optional().stringType()
.name("nstring").type().nullable().stringType().stringDefault("def")
.name("rbytes").type().bytesType().noDefault()
.name("obytes").type().optional().bytesType()
.name("nbytes").type().nullable().bytesType().bytesDefault(new byte[] {1,2,3})
.endRecord();
Schema shortcut = SchemaBuilder.record("Blah").fields()
.requiredBoolean("rbool")
.optionalBoolean("obool")
.nullableBoolean("nbool", true)
.requiredInt("rint")
.optionalInt("oint")
.nullableInt("nint", 1)
.requiredLong("rlong")
.optionalLong("olong")
.nullableLong("nlong", 2L)
.requiredFloat("rfloat")
.optionalFloat("ofloat")
.nullableFloat("nfloat", -1.1f)
.requiredDouble("rdouble")
.optionalDouble("odouble")
.nullableDouble("ndouble", 99.9d)
.requiredString("rstring")
.optionalString("ostring")
.nullableString("nstring", "def")
.requiredBytes("rbytes")
.optionalBytes("obytes")
.nullableBytes("nbytes", new byte[] {1,2,3})
.endRecord();
Assert.assertEquals(full, shortcut);
}
@Test
public void testNames() {
// no contextual namespace
Schema r = SchemaBuilder.record("Rec").fields()
.name("f0").type().fixed("org.foo.MyFixed").size(1).noDefault()
.name("f1").type("org.foo.MyFixed").noDefault()
.name("f2").type("org.foo.MyFixed", "").noDefault()
.name("f3").type("org.foo.MyFixed", null).noDefault()
.name("f4").type("org.foo.MyFixed", "ignorethis").noDefault()
.name("f5").type("MyFixed", "org.foo").noDefault()
.endRecord();
Schema expected = Schema.createFixed("org.foo.MyFixed", null, null, 1);
checkField(r, expected, "f0");
checkField(r, expected, "f1");
checkField(r, expected, "f2");
checkField(r, expected, "f3");
checkField(r, expected, "f4");
checkField(r, expected, "f5");
// context namespace
Schema f = SchemaBuilder.builder("").fixed("Foo").size(1);
Assert.assertEquals(Schema.createFixed("Foo", null, null, 1), f);
// context namespace from record matches
r = SchemaBuilder.record("Rec").namespace("org.foo").fields()
.name("f0").type().fixed("MyFixed").size(1).noDefault()
.name("f1").type("org.foo.MyFixed").noDefault()
.name("f2").type("org.foo.MyFixed", "").noDefault()
.name("f3").type("org.foo.MyFixed", null).noDefault()
.name("f4").type("org.foo.MyFixed", "ignorethis").noDefault()
.name("f5").type("MyFixed", "org.foo").noDefault()
.name("f6").type("MyFixed", null).noDefault()
.name("f7").type("MyFixed").noDefault()
.endRecord();
checkField(r, expected, "f0");
checkField(r, expected, "f1");
checkField(r, expected, "f2");
checkField(r, expected, "f3");
checkField(r, expected, "f4");
checkField(r, expected, "f5");
checkField(r, expected, "f6");
checkField(r, expected, "f7");
// context namespace from record does not match
r = SchemaBuilder.record("Rec").namespace("org.rec").fields()
.name("f0").type().fixed("MyFixed").namespace("org.foo").size(1).noDefault()
.name("f1").type("org.foo.MyFixed").noDefault()
.name("f2").type("org.foo.MyFixed", "").noDefault()
.name("f3").type("org.foo.MyFixed", null).noDefault()
.name("f4").type("org.foo.MyFixed", "ignorethis").noDefault()
.name("f5").type("MyFixed", "org.foo").noDefault()
.endRecord();
checkField(r, expected, "f0");
checkField(r, expected, "f1");
checkField(r, expected, "f2");
checkField(r, expected, "f3");
checkField(r, expected, "f4");
checkField(r, expected, "f5");
// context namespace from record, nested has no namespace
expected = Schema.createFixed("MyFixed", null, null, 1);
r = SchemaBuilder.record("Rec").namespace("org.rec").fields()
.name("f0").type().fixed("MyFixed").namespace("").size(1).noDefault()
.name("f1").type("MyFixed", "").noDefault()
.endRecord();
checkField(r, expected, "f0");
checkField(r, expected, "f1");
// mimic names of primitives, but with a namesapce. This is OK
SchemaBuilder.fixed("org.test.long").size(1);
SchemaBuilder.fixed("long").namespace("org.test").size(1);
SchemaBuilder.builder("org.test").fixed("long").size(1);
}
private void checkField(Schema r, Schema expected, String name) {
Assert.assertEquals(expected, r.getField(name).schema());
}
@Test(expected=SchemaParseException.class)
public void testNamesFailRedefined() {
SchemaBuilder.record("Rec").fields()
.name("f0").type().enumeration("MyEnum").symbols("A", "B").enumDefault("A")
.name("f1").type().enumeration("MyEnum").symbols("X", "Y").noDefault()
.endRecord();
}
@Test(expected=SchemaParseException.class)
public void testNamesFailAbsent() {
SchemaBuilder.builder().type("notdefined");
}
@Test(expected=AvroTypeException.class)
public void testNameReserved() {
SchemaBuilder.fixed("long").namespace("").size(1);
}
@Test
public void testFieldTypesAndDefaultValues() {
byte[] bytedef = new byte[]{3};
ByteBuffer bufdef = ByteBuffer.wrap(bytedef);
String strdef = "\u0003";
HashMap<String, String> mapdef = new HashMap<String, String>();
mapdef.put("a", "A");
ArrayList<String> arrdef = new ArrayList<String>();
arrdef.add("arr");
Schema rec = SchemaBuilder.record("inner").fields()
.name("f").type().intType().noDefault()
.endRecord();
Schema rec2 = SchemaBuilder.record("inner2").fields()
.name("f2").type().intType().noDefault()
.endRecord();
GenericData.Record recdef =
new GenericRecordBuilder(rec).set("f", 1).build();
GenericData.Record recdef2 =
new GenericRecordBuilder(rec2).set("f2", 2).build();
Schema r = SchemaBuilder.record("r").fields()
.name("boolF").type().booleanType().booleanDefault(false)
.name("intF").type().intType().intDefault(1)
.name("longF").type().longType().longDefault(2L)
.name("floatF").type().floatType().floatDefault(3.0f)
.name("doubleF").type().doubleType().doubleDefault(4.0d)
.name("stringF").type().stringType().stringDefault("def")
.name("bytesF1").type().bytesType().bytesDefault(bytedef)
.name("bytesF2").type().bytesType().bytesDefault(bufdef)
.name("bytesF3").type().bytesType().bytesDefault(strdef)
.name("nullF").type().nullType().nullDefault()
.name("fixedF1").type().fixed("F1").size(1).fixedDefault(bytedef)
.name("fixedF2").type().fixed("F2").size(1).fixedDefault(bufdef)
.name("fixedF3").type().fixed("F3").size(1).fixedDefault(strdef)
.name("enumF").type().enumeration("E1").symbols("S").enumDefault("S")
.name("mapF").type().map().values().stringType()
.mapDefault(mapdef)
.name("arrayF").type().array().items().stringType()
.arrayDefault(arrdef)
.name("recordF").type().record("inner").fields()
.name("f").type().intType().noDefault()
.endRecord().recordDefault(recdef)
.name("byName").type("E1").withDefault("S")
// union builders, one for each 'first type' in a union:
.name("boolU").type().unionOf().booleanType().and()
.intType().endUnion().booleanDefault(false)
.name("intU").type().unionOf().intType().and()
.longType().endUnion().intDefault(1)
.name("longU").type().unionOf().longType().and()
.intType().endUnion().longDefault(2L)
.name("floatU").type().unionOf().floatType().and()
.intType().endUnion().floatDefault(3.0f)
.name("doubleU").type().unionOf().doubleType().and()
.intType().endUnion().doubleDefault(4.0d)
.name("stringU").type().unionOf().stringType().and()
.intType().endUnion().stringDefault("def")
.name("bytesU").type().unionOf().bytesType().and()
.intType().endUnion().bytesDefault(bytedef)
.name("nullU").type().unionOf().nullType().and()
.intType().endUnion().nullDefault()
.name("fixedU").type().unionOf().fixed("F4").size(1).and()
.intType().endUnion().fixedDefault(bytedef)
.name("enumU").type().unionOf().enumeration("E2").symbols("SS").and()
.intType().endUnion().enumDefault("SS")
.name("mapU").type().unionOf().map().values().stringType().and()
.intType().endUnion().mapDefault(mapdef)
.name("arrayU").type().unionOf().array().items().stringType().and()
.intType().endUnion().arrayDefault(arrdef)
.name("recordU").type().unionOf().record("inner2").fields()
.name("f2").type().intType().noDefault()
.endRecord().and().intType().endUnion().recordDefault(recdef2)
.endRecord();
GenericData.Record newRec =
new GenericRecordBuilder(r).build();
Assert.assertEquals(false, newRec.get("boolF"));
Assert.assertEquals(false, newRec.get("boolU"));
Assert.assertEquals(1, newRec.get("intF"));
Assert.assertEquals(1, newRec.get("intU"));
Assert.assertEquals(2L, newRec.get("longF"));
Assert.assertEquals(2L, newRec.get("longU"));
Assert.assertEquals(3f, newRec.get("floatF"));
Assert.assertEquals(3f, newRec.get("floatU"));
Assert.assertEquals(4d, newRec.get("doubleF"));
Assert.assertEquals(4d, newRec.get("doubleU"));
Assert.assertEquals("def", newRec.get("stringF").toString());
Assert.assertEquals("def", newRec.get("stringU").toString());
Assert.assertEquals(bufdef, newRec.get("bytesF1"));
Assert.assertEquals(bufdef, newRec.get("bytesF2"));
Assert.assertEquals(bufdef, newRec.get("bytesF3"));
Assert.assertEquals(bufdef, newRec.get("bytesU"));
Assert.assertNull(newRec.get("nullF"));
Assert.assertNull(newRec.get("nullU"));
Assert.assertArrayEquals(bytedef,
((GenericData.Fixed)newRec.get("fixedF1")).bytes());
Assert.assertArrayEquals(bytedef,
((GenericData.Fixed)newRec.get("fixedF2")).bytes());
Assert.assertArrayEquals(bytedef,
((GenericData.Fixed)newRec.get("fixedF3")).bytes());
Assert.assertArrayEquals(bytedef,
((GenericData.Fixed)newRec.get("fixedU")).bytes());
Assert.assertEquals("S", newRec.get("enumF").toString());
Assert.assertEquals("SS", newRec.get("enumU").toString());
@SuppressWarnings("unchecked")
Map<CharSequence, CharSequence> map =
(Map<CharSequence, CharSequence>) newRec.get("mapF");
Assert.assertEquals(mapdef.size(), map.size());
for(Map.Entry<CharSequence, CharSequence> e : map.entrySet()) {
Assert.assertEquals(
mapdef.get(e.getKey().toString()), e.getValue().toString());
}
Assert.assertEquals(newRec.get("mapF"), newRec.get("mapU"));
@SuppressWarnings("unchecked")
GenericData.Array<CharSequence> arr =
(GenericData.Array<CharSequence>) newRec.get("arrayF");
Assert.assertEquals(arrdef.size(), arr.size());
for(CharSequence c : arr) {
Assert.assertTrue(arrdef.contains(c.toString()));
}
Assert.assertEquals(newRec.get("arrF"), newRec.get("arrU"));
Assert.assertEquals(recdef, newRec.get("recordF"));
Assert.assertEquals(recdef2, newRec.get("recordU"));
Assert.assertEquals("S", newRec.get("byName").toString());
}
@Test(expected=SchemaBuilderException.class)
public void testBadDefault() {
SchemaBuilder.record("r").fields()
.name("f").type(Schema.create(Schema.Type.INT)).withDefault(new Object())
.endRecord();
}
@Test
public void testUnionFieldBuild() {
SchemaBuilder.record("r").fields()
.name("allUnion").type().unionOf()
.booleanType().and()
.intType().and()
.longType().and()
.floatType().and()
.doubleType().and()
.stringType().and()
.bytesType().and()
.nullType().and()
.fixed("Fix").size(1).and()
.enumeration("Enu").symbols("Q").and()
.array().items().intType().and()
.map().values().longType().and()
.record("Rec").fields()
.name("one").type("Fix").noDefault()
.endRecord()
.endUnion().booleanDefault(false)
.endRecord();
}
@Test
public void testDefaults() throws IOException {
Schema writeSchema = SchemaBuilder.record("r").fields()
.name("requiredInt").type().intType().noDefault()
.name("optionalInt").type().optional().intType()
.name("nullableIntWithDefault").type().nullable().intType().intDefault(3)
.endRecord();
GenericData.Record rec1 = new GenericRecordBuilder(writeSchema)
.set("requiredInt", 1)
.build();
Assert.assertEquals(1, rec1.get("requiredInt"));
Assert.assertEquals(null, rec1.get("optionalInt"));
Assert.assertEquals(3, rec1.get("nullableIntWithDefault"));
GenericData.Record rec2 = new GenericRecordBuilder(writeSchema)
.set("requiredInt", 1)
.set("optionalInt", 2)
.set("nullableIntWithDefault", 13)
.build();
Assert.assertEquals(1, rec2.get("requiredInt"));
Assert.assertEquals(2, rec2.get("optionalInt"));
Assert.assertEquals(13, rec2.get("nullableIntWithDefault"));
// write to file
DataFileWriter<Object> writer =
new DataFileWriter<Object>(new GenericDatumWriter<Object>());
writer.create(writeSchema, FILE);
writer.append(rec1);
writer.append(rec2);
writer.close();
Schema readSchema = SchemaBuilder.record("r").fields()
.name("requiredInt").type().intType().noDefault()
.name("optionalInt").type().optional().intType()
.name("nullableIntWithDefault").type().nullable().intType().intDefault(3)
.name("newOptionalInt").type().optional().intType()
.name("newNullableIntWithDefault").type().nullable().intType().intDefault(5)
.endRecord();
DataFileReader<GenericData.Record> reader =
new DataFileReader<GenericData.Record>(FILE,
new GenericDatumReader<GenericData.Record>(writeSchema, readSchema));
GenericData.Record rec1read = reader.iterator().next();
Assert.assertEquals(1, rec1read.get("requiredInt"));
Assert.assertEquals(null, rec1read.get("optionalInt"));
Assert.assertEquals(3, rec1read.get("nullableIntWithDefault"));
Assert.assertEquals(null, rec1read.get("newOptionalInt"));
Assert.assertEquals(5, rec1read.get("newNullableIntWithDefault"));
GenericData.Record rec2read = reader.iterator().next();
Assert.assertEquals(1, rec2read.get("requiredInt"));
Assert.assertEquals(2, rec2read.get("optionalInt"));
Assert.assertEquals(13, rec2read.get("nullableIntWithDefault"));
Assert.assertEquals(null, rec2read.get("newOptionalInt"));
Assert.assertEquals(5, rec2read.get("newNullableIntWithDefault"));
}
}