| /** |
| * 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.trevni.avro; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.Arrays; |
| |
| import org.apache.trevni.ValueType; |
| import org.apache.trevni.ColumnMetaData; |
| import org.apache.trevni.ColumnFileMetaData; |
| |
| import org.apache.avro.Schema; |
| |
| import org.junit.Test; |
| import static org.junit.Assert.*; |
| |
| public class TestShredder { |
| |
| private static final int COUNT = 100; |
| private static final File FILE = new File("target", "test.trv"); |
| |
| @Test public void testPrimitives() throws Exception { |
| check(Schema.create(Schema.Type.NULL), |
| new ColumnMetaData("null", ValueType.NULL)); |
| check(Schema.create(Schema.Type.BOOLEAN), |
| new ColumnMetaData("boolean", ValueType.BOOLEAN)); |
| |
| check(Schema.create(Schema.Type.INT), |
| new ColumnMetaData("int", ValueType.INT)); |
| check(Schema.create(Schema.Type.LONG), |
| new ColumnMetaData("long", ValueType.LONG)); |
| |
| check(Schema.create(Schema.Type.FLOAT), |
| new ColumnMetaData("float", ValueType.FLOAT)); |
| check(Schema.create(Schema.Type.DOUBLE), |
| new ColumnMetaData("double", ValueType.DOUBLE)); |
| |
| check(Schema.create(Schema.Type.BYTES), |
| new ColumnMetaData("bytes", ValueType.BYTES)); |
| check(Schema.create(Schema.Type.STRING), |
| new ColumnMetaData("string", ValueType.STRING)); |
| |
| check(Schema.createEnum("E", null, null, Arrays.asList("X","Y","Z")), |
| new ColumnMetaData("E", ValueType.INT)); |
| check(Schema.createFixed("F", null, null, 5), |
| new ColumnMetaData("F", ValueType.BYTES)); |
| } |
| |
| private static final String SIMPLE_FIELDS = |
| "{\"name\":\"x\",\"type\":\"int\"},"+ |
| "{\"name\":\"y\",\"type\":\"string\"}"; |
| |
| private static final String SIMPLE_RECORD = |
| "{\"type\":\"record\",\"name\":\"R\",\"fields\":[" |
| +SIMPLE_FIELDS |
| +"]}"; |
| |
| @Test public void testSimpleRecord() throws Exception { |
| check(Schema.parse(SIMPLE_RECORD), |
| new ColumnMetaData("x", ValueType.INT), |
| new ColumnMetaData("y", ValueType.STRING)); |
| } |
| |
| @Test public void testDefaultValue() throws Exception { |
| String s = |
| "{\"type\":\"record\",\"name\":\"R\",\"fields\":[" |
| +SIMPLE_FIELDS+"," |
| +"{\"name\":\"z\",\"type\":\"int\"," |
| +"\"default\":1,\""+RandomData.USE_DEFAULT+"\":true}" |
| +"]}"; |
| checkWrite(Schema.parse(SIMPLE_RECORD)); |
| checkRead(Schema.parse(s)); |
| } |
| |
| @Test public void testNestedRecord() throws Exception { |
| String s = |
| "{\"type\":\"record\",\"name\":\"S\",\"fields\":[" |
| +"{\"name\":\"x\",\"type\":\"int\"}," |
| +"{\"name\":\"R\",\"type\":"+SIMPLE_RECORD+"}," |
| +"{\"name\":\"y\",\"type\":\"string\"}" |
| +"]}"; |
| check(Schema.parse(s), |
| new ColumnMetaData("x", ValueType.INT), |
| new ColumnMetaData("R#x", ValueType.INT), |
| new ColumnMetaData("R#y", ValueType.STRING), |
| new ColumnMetaData("y", ValueType.STRING)); |
| } |
| |
| @Test public void testNamedRecord() throws Exception { |
| String s = |
| "{\"type\":\"record\",\"name\":\"S\",\"fields\":[" |
| +"{\"name\":\"R1\",\"type\":"+SIMPLE_RECORD+"}," |
| +"{\"name\":\"R2\",\"type\":\"R\"}" |
| +"]}"; |
| check(Schema.parse(s), |
| new ColumnMetaData("R1#x", ValueType.INT), |
| new ColumnMetaData("R1#y", ValueType.STRING), |
| new ColumnMetaData("R2#x", ValueType.INT), |
| new ColumnMetaData("R2#y", ValueType.STRING)); |
| } |
| |
| @Test public void testSimpleArray() throws Exception { |
| String s = "{\"type\":\"array\",\"items\":\"long\"}"; |
| check(Schema.parse(s), |
| new ColumnMetaData("[]", ValueType.LONG).isArray(true)); |
| } |
| |
| private static final String RECORD_ARRAY = |
| "{\"type\":\"array\",\"items\":"+SIMPLE_RECORD+"}"; |
| |
| @Test public void testArray() throws Exception { |
| ColumnMetaData p = new ColumnMetaData("[]", ValueType.NULL).isArray(true); |
| check(Schema.parse(RECORD_ARRAY), |
| p, |
| new ColumnMetaData("[]#x", ValueType.INT).setParent(p), |
| new ColumnMetaData("[]#y", ValueType.STRING).setParent(p)); |
| } |
| |
| @Test public void testSimpleUnion() throws Exception { |
| String s = "[\"int\",\"string\"]"; |
| check(Schema.parse(s), |
| new ColumnMetaData("int", ValueType.INT).isArray(true), |
| new ColumnMetaData("string", ValueType.STRING).isArray(true)); |
| } |
| |
| @Test public void testSimpleOptional() throws Exception { |
| String s = "[\"null\",\"string\"]"; |
| check(Schema.parse(s), |
| new ColumnMetaData("string", ValueType.STRING).isArray(true)); |
| } |
| |
| private static final String UNION = "[\"null\",\"int\","+SIMPLE_RECORD+"]"; |
| |
| @Test public void testUnion() throws Exception { |
| ColumnMetaData p = new ColumnMetaData("R", ValueType.NULL).isArray(true); |
| check(Schema.parse(UNION), |
| new ColumnMetaData("int", ValueType.INT).isArray(true), |
| p, |
| new ColumnMetaData("R#x", ValueType.INT).setParent(p), |
| new ColumnMetaData("R#y", ValueType.STRING).setParent(p)); |
| } |
| |
| @Test public void testNestedArray() throws Exception { |
| String s = |
| "{\"type\":\"record\",\"name\":\"S\",\"fields\":[" |
| +"{\"name\":\"x\",\"type\":\"int\"}," |
| +"{\"name\":\"A\",\"type\":"+RECORD_ARRAY+"}," |
| +"{\"name\":\"y\",\"type\":\"string\"}" |
| +"]}"; |
| ColumnMetaData p = new ColumnMetaData("A[]", ValueType.NULL).isArray(true); |
| check(Schema.parse(s), |
| new ColumnMetaData("x", ValueType.INT), |
| p, |
| new ColumnMetaData("A[]#x", ValueType.INT).setParent(p), |
| new ColumnMetaData("A[]#y", ValueType.STRING).setParent(p), |
| new ColumnMetaData("y", ValueType.STRING)); |
| } |
| |
| @Test public void testNestedUnion() throws Exception { |
| String s = |
| "{\"type\":\"record\",\"name\":\"S\",\"fields\":[" |
| +"{\"name\":\"x\",\"type\":\"int\"}," |
| +"{\"name\":\"u\",\"type\":"+UNION+"}," |
| +"{\"name\":\"y\",\"type\":\"string\"}" |
| +"]}"; |
| ColumnMetaData p = new ColumnMetaData("u/R", ValueType.NULL).isArray(true); |
| check(Schema.parse(s), |
| new ColumnMetaData("x", ValueType.INT), |
| new ColumnMetaData("u/int", ValueType.INT).isArray(true), |
| p, |
| new ColumnMetaData("u/R#x", ValueType.INT).setParent(p), |
| new ColumnMetaData("u/R#y", ValueType.STRING).setParent(p), |
| new ColumnMetaData("y", ValueType.STRING)); |
| } |
| |
| @Test public void testUnionInArray() throws Exception { |
| String s = |
| "{\"type\":\"record\",\"name\":\"S\",\"fields\":[" |
| +"{\"name\":\"a\",\"type\":{\"type\":\"array\",\"items\":"+UNION+"}}" |
| +"]}"; |
| ColumnMetaData p = new ColumnMetaData("a[]",ValueType.NULL).isArray(true); |
| ColumnMetaData r = new ColumnMetaData("a[]/R", ValueType.NULL) |
| .setParent(p) |
| .isArray(true); |
| check(Schema.parse(s), |
| p, |
| new ColumnMetaData("a[]/int", ValueType.INT) |
| .setParent(p) |
| .isArray(true), |
| r, |
| new ColumnMetaData("a[]/R#x", ValueType.INT).setParent(r), |
| new ColumnMetaData("a[]/R#y", ValueType.STRING).setParent(r)); |
| } |
| |
| @Test public void testArrayInUnion() throws Exception { |
| String s = |
| "{\"type\":\"record\",\"name\":\"S\",\"fields\":[" |
| +"{\"name\":\"a\",\"type\":[\"int\","+RECORD_ARRAY+"]}]}"; |
| ColumnMetaData q = new ColumnMetaData("a/array",ValueType.NULL) |
| .isArray(true); |
| ColumnMetaData r = new ColumnMetaData("a/array[]", ValueType.NULL) |
| .setParent(q) |
| .isArray(true); |
| check(Schema.parse(s), |
| new ColumnMetaData("a/int", ValueType.INT).isArray(true), |
| q, |
| r, |
| new ColumnMetaData("a/array[]#x", ValueType.INT).setParent(r), |
| new ColumnMetaData("a/array[]#y", ValueType.STRING).setParent(r)); |
| } |
| |
| @Test public void testSimpleMap() throws Exception { |
| String s = "{\"type\":\"map\",\"values\":\"long\"}"; |
| ColumnMetaData p = new ColumnMetaData(">", ValueType.NULL).isArray(true); |
| check(Schema.parse(s), |
| p, |
| new ColumnMetaData(">key", ValueType.STRING).setParent(p), |
| new ColumnMetaData(">value", ValueType.LONG).setParent(p)); |
| } |
| |
| @Test public void testMap() throws Exception { |
| String s = "{\"type\":\"map\",\"values\":"+SIMPLE_RECORD+"}"; |
| ColumnMetaData p = new ColumnMetaData(">", ValueType.NULL).isArray(true); |
| check(Schema.parse(s), |
| p, |
| new ColumnMetaData(">key", ValueType.STRING).setParent(p), |
| new ColumnMetaData(">value#x", ValueType.INT).setParent(p), |
| new ColumnMetaData(">value#y", ValueType.STRING).setParent(p)); |
| } |
| |
| private void check(Schema s, ColumnMetaData... expected) throws Exception { |
| ColumnMetaData[] shredded = new AvroColumnator(s).getColumns(); |
| assertEquals(expected.length, shredded.length); |
| for (int i = 0; i < expected.length; i++) |
| assertEquals(expected[i].toString(), shredded[i].toString()); |
| checkWrite(s); |
| checkRead(s); |
| } |
| |
| private void checkWrite(Schema schema) throws IOException { |
| AvroColumnWriter<Object> writer = |
| new AvroColumnWriter<Object>(schema, new ColumnFileMetaData()); |
| int count = 0; |
| for (Object datum : new RandomData(schema, COUNT)) { |
| //System.out.println("datum="+datum); |
| writer.write(datum); |
| } |
| writer.writeTo(FILE); |
| } |
| |
| private void checkRead(Schema schema) throws IOException { |
| AvroColumnReader<Object> reader = |
| new AvroColumnReader<Object>(new AvroColumnReader.Params(FILE) |
| .setSchema(schema)); |
| for (Object expected : new RandomData(schema, COUNT)) |
| assertEquals(expected, reader.next()); |
| reader.close(); |
| } |
| |
| } |