/* * Copyright © 2014 Cask Data, Inc. * * Licensed 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 co.cask.cdap.explore.table; import co.cask.cdap.api.data.schema.UnsupportedTypeException; import com.google.common.base.Objects; import com.google.common.reflect.TypeToken; import org.junit.Assert; import org.junit.Test; import java.lang.reflect.Type; import java.util.Collection; import java.util.List; import java.util.Map; /** * */ public class SchemaConverterTest { public static class KeyValue { private final String key; private final Value value; public KeyValue(String key, Value value) { this.key = key; this.value = value; } @SuppressWarnings("UnusedDeclaration") public String getKey() { return key; } @SuppressWarnings("UnusedDeclaration") public Value getValue() { return value; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } KeyValue that = (KeyValue) o; return Objects.equal(this.key, that.key) && Objects.equal(this.value, that.value); } @Override public int hashCode() { return Objects.hashCode(key, value); } public static class Value { private final String name; private final List<Integer> ints; public Value(String name, List<Integer> ints) { this.name = name; this.ints = ints; } @SuppressWarnings("UnusedDeclaration") public String getName() { return name; } @SuppressWarnings("UnusedDeclaration") public List<Integer> getInts() { return ints; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } Value that = (Value) o; return Objects.equal(this.name, that.name) && Objects.equal(this.ints, that.ints); } @Override public int hashCode() { return Objects.hashCode(name, ints); } } } @SuppressWarnings("unused") enum Foo { FOO, BAR } @SuppressWarnings("unused") static class Record { int a; long b; boolean c; float d; double e; String f; byte[] g; Foo[] h; Collection<Boolean> i; Map<Integer, String> j; } @SuppressWarnings("unused") static class Record2 { String s2; Record record; } @SuppressWarnings("unused") static class Record3 { int i3; Record2 record2; } @SuppressWarnings("unused") public class Recursive { private final int a; private final Recursive b; private final int c; public Recursive(int a, Recursive b) { this.a = a; this.b = b; this.c = a; } } @SuppressWarnings("unused") public class TransitiveRecursive { private final boolean empty; private final List<TransitiveRecursive> children; public TransitiveRecursive(boolean empty, List<TransitiveRecursive> children) { this.empty = empty; this.children = children; } } @SuppressWarnings("unused") public class Value { private int a; } @SuppressWarnings("unused") public class NotRecursive { private final Value a; private final Value b; public NotRecursive(Value a, Value b) { this.a = a; this.b = b; } } @Test public void testHiveSchemaFor() throws Exception { Assert.assertEquals("(a int, b bigint, c boolean, d float, e double, f string, g binary, " + "h array<string>, i array<boolean>, j map<int,string>)", SchemaConverter.toHiveSchema(Record.class)); Assert.assertEquals("(key string, value struct<ints:array<int>,name:string>)", SchemaConverter.toHiveSchema(KeyValue.class)); Assert.assertEquals("(i3 int, record2 struct<" + "record:struct<a:int,b:bigint,c:boolean,d:float,e:double,f:string,g:binary," + "h:array<string>,i:array<boolean>,j:map<int,string>>," + "s2:string>)", SchemaConverter.toHiveSchema(Record3.class)); } @Test public void testUnsupportedTypes() { verifyUnsupportedSchema(Integer.class); verifyUnsupportedSchema(String.class); verifyUnsupportedSchema(new TypeToken<List<Integer>>() { }.getType()); verifyUnsupportedSchema(new TypeToken<Map<String, Integer>>() { }.getType()); verifyUnsupportedSchema(Recursive.class); verifyUnsupportedSchema(TransitiveRecursive.class); } @Test public void testSupportedTypes() throws Exception { // Should not throw an exception SchemaConverter.toHiveSchema(NotRecursive.class); } private void verifyUnsupportedSchema(Type type) { String schema; try { schema = SchemaConverter.toHiveSchema(type); } catch (UnsupportedTypeException e) { // expected return; } Assert.fail("Type " + type + " should not be supported and cause exception but returned " + schema); } }