| /* |
| * 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.calcite.avatica.test; |
| |
| import org.apache.calcite.avatica.AvaticaUtils; |
| import org.apache.calcite.avatica.ConnectionConfigImpl; |
| import org.apache.calcite.avatica.ConnectionProperty; |
| import org.apache.calcite.avatica.util.ByteString; |
| |
| import org.junit.Test; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.nio.charset.StandardCharsets; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.LinkedHashSet; |
| import java.util.Locale; |
| import java.util.Properties; |
| import java.util.Set; |
| |
| import static org.apache.calcite.avatica.AvaticaUtils.skipFully; |
| |
| import static org.hamcrest.CoreMatchers.is; |
| import static org.hamcrest.CoreMatchers.nullValue; |
| import static org.junit.Assert.assertArrayEquals; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotEquals; |
| import static org.junit.Assert.assertThat; |
| import static org.junit.Assert.fail; |
| |
| /** |
| * Unit test for Avatica utilities. |
| */ |
| public class AvaticaUtilsTest { |
| @Test public void testInstantiatePlugin() { |
| final String s = |
| AvaticaUtils.instantiatePlugin(String.class, "java.lang.String"); |
| assertThat(s, is("")); |
| |
| // No default constructor or INSTANCE member |
| try { |
| final Integer i = |
| AvaticaUtils.instantiatePlugin(Integer.class, "java.lang.Integer"); |
| fail("expected error, got " + i); |
| } catch (Throwable e) { |
| assertThat(e.getMessage(), |
| is("Property 'java.lang.Integer' not valid for plugin type java.lang.Integer")); |
| } |
| |
| final BigInteger b = |
| AvaticaUtils.instantiatePlugin(BigInteger.class, "java.math.BigInteger#ONE"); |
| assertThat(b, is(BigInteger.ONE)); |
| |
| try { |
| final BigInteger b2 = |
| AvaticaUtils.instantiatePlugin(BigInteger.class, |
| "java.math.BigInteger.ONE"); |
| fail("expected error, got " + b2); |
| } catch (Throwable e) { |
| assertThat(e.getMessage(), |
| is("Property 'java.math.BigInteger.ONE' not valid for plugin type java.math.BigInteger")); |
| } |
| } |
| |
| /** Unit test for |
| * {@link org.apache.calcite.avatica.AvaticaUtils#unique(java.lang.String)}. */ |
| @Test public void testUnique() { |
| // Below, the "probably" comments indicate the strings that will be |
| // generated the first time you run the test. |
| final Set<String> list = new LinkedHashSet<>(); |
| list.add(AvaticaUtils.unique("a")); // probably "a" |
| assertThat(list.size(), is(1)); |
| list.add(AvaticaUtils.unique("a")); // probably "a_1" |
| assertThat(list.size(), is(2)); |
| list.add(AvaticaUtils.unique("b")); // probably "b" |
| assertThat(list.size(), is(3)); |
| list.add(AvaticaUtils.unique("a_1")); // probably "a_1_3" |
| assertThat(list.size(), is(4)); |
| list.add(AvaticaUtils.unique("A")); // probably "A" |
| assertThat(list.size(), is(5)); |
| list.add(AvaticaUtils.unique("a")); // probably "a_5" |
| assertThat(list.size(), is(6)); |
| } |
| |
| /** Tests connect string properties. */ |
| @Test public void testConnectionProperty() { |
| final ConnectionPropertyImpl n = new ConnectionPropertyImpl("N", |
| BigDecimal.valueOf(100), ConnectionProperty.Type.NUMBER); |
| |
| final Properties properties = new Properties(); |
| ConnectionConfigImpl.PropEnv env = n.wrap(properties); |
| assertThat(env.getInt(), is(100)); |
| assertThat(env.getInt(-45), is(-45)); |
| properties.setProperty(n.name, "123"); |
| assertThat(env.getInt(), is(100)); |
| env = n.wrap(properties); |
| assertThat(env.getInt(), is(123)); |
| assertThat(env.getInt(-45), is(123)); |
| |
| properties.setProperty(n.name, "10k"); |
| env = n.wrap(properties); |
| assertThat(env.getInt(), is(10 * 1024)); |
| |
| properties.setProperty(n.name, "-0.5k"); |
| env = n.wrap(properties); |
| assertThat(env.getInt(), is(-512)); |
| |
| properties.setProperty(n.name, "10m"); |
| env = n.wrap(properties); |
| assertThat(env.getInt(), is(10 * 1024 * 1024)); |
| assertThat(env.getLong(), is(10L * 1024 * 1024)); |
| assertThat(env.getDouble(), is(10D * 1024 * 1024)); |
| |
| properties.setProperty(n.name, "-2M"); |
| env = n.wrap(properties); |
| assertThat(env.getInt(), is(-2 * 1024 * 1024)); |
| |
| properties.setProperty(n.name, "10g"); |
| env = n.wrap(properties); |
| assertThat(env.getLong(), is(10L * 1024 * 1024 * 1024)); |
| |
| final ConnectionPropertyImpl b = new ConnectionPropertyImpl("B", |
| true, ConnectionProperty.Type.BOOLEAN); |
| |
| env = b.wrap(properties); |
| assertThat(env.getBoolean(), is(true)); |
| assertThat(env.getBoolean(true), is(true)); |
| assertThat(env.getBoolean(false), is(false)); |
| |
| properties.setProperty(b.name, "false"); |
| env = b.wrap(properties); |
| assertThat(env.getBoolean(), is(false)); |
| |
| final ConnectionPropertyImpl s = new ConnectionPropertyImpl("S", |
| "foo", ConnectionProperty.Type.STRING); |
| |
| env = s.wrap(properties); |
| assertThat(env.getString(), is("foo")); |
| assertThat(env.getString("baz"), is("baz")); |
| |
| properties.setProperty(s.name, " "); |
| env = s.wrap(properties); |
| assertThat(env.getString(), is(" ")); |
| |
| try { |
| final ConnectionPropertyImpl t = |
| new ConnectionPropertyImpl("T", null, ConnectionProperty.Type.ENUM); |
| fail("should throw if you specify an enum property without a class, got " |
| + t); |
| } catch (AssertionError e) { |
| assertThat(e.getMessage(), is("must specify value class for an ENUM")); |
| // ok |
| } |
| |
| // An enum with a default value |
| final ConnectionPropertyImpl t = new ConnectionPropertyImpl("T", Size.BIG, |
| ConnectionProperty.Type.ENUM, Size.class); |
| env = t.wrap(properties); |
| assertThat(env.getEnum(Size.class), is(Size.BIG)); |
| assertThat(env.getEnum(Size.class, Size.SMALL), is(Size.SMALL)); |
| assertThat(env.getEnum(Size.class, null), nullValue()); |
| try { |
| final Weight envEnum = env.getEnum(Weight.class, null); |
| fail("expected error, got " + envEnum); |
| } catch (AssertionError e) { |
| assertThat(e.getMessage(), |
| is("wrong value class; expected " + Size.class)); |
| } |
| |
| // An enum with a default value that is an anonymous enum, |
| // not specifying value type. |
| final ConnectionPropertyImpl v = new ConnectionPropertyImpl("V", |
| Size.SMALL, ConnectionProperty.Type.ENUM); |
| env = v.wrap(properties); |
| assertThat(env.getEnum(Size.class), is(Size.SMALL)); |
| assertThat(env.getEnum(Size.class, Size.BIG), is(Size.BIG)); |
| assertThat(env.getEnum(Size.class, null), nullValue()); |
| try { |
| final Weight envEnum = env.getEnum(Weight.class, null); |
| fail("expected error, got " + envEnum); |
| } catch (AssertionError e) { |
| assertThat(e.getMessage(), |
| is("wrong value class; expected " + Size.class)); |
| } |
| |
| // An enum with no default value |
| final ConnectionPropertyImpl u = new ConnectionPropertyImpl("U", null, |
| ConnectionProperty.Type.ENUM, Size.class); |
| env = u.wrap(properties); |
| assertThat(env.getEnum(Size.class), nullValue()); |
| assertThat(env.getEnum(Size.class, Size.SMALL), is(Size.SMALL)); |
| assertThat(env.getEnum(Size.class, null), nullValue()); |
| try { |
| final Weight envEnum = env.getEnum(Weight.class, null); |
| fail("expected error, got " + envEnum); |
| } catch (AssertionError e) { |
| assertThat(e.getMessage(), |
| is("wrong value class; expected " + Size.class)); |
| } |
| } |
| |
| @Test public void testLongToIntegerTranslation() { |
| long[] longValues = new long[] {Integer.MIN_VALUE, -5, 0, 1, Integer.MAX_VALUE, |
| ((long) Integer.MAX_VALUE) + 1L, Long.MAX_VALUE}; |
| int[] convertedValues = AvaticaUtils.toSaturatedInts(longValues); |
| int[] intValues = new int[] {Integer.MIN_VALUE, -5, 0, 1, Integer.MAX_VALUE, |
| Integer.MAX_VALUE, Integer.MAX_VALUE}; |
| assertArrayEquals(convertedValues, intValues); |
| } |
| |
| @Test public void testByteString() { |
| final byte[] bytes = {3, 14, 15, 92, 0, 65, 35, 0}; |
| final ByteString s = new ByteString(bytes); |
| final ByteString s2 = new ByteString(bytes.clone()); |
| final ByteString s3 = new ByteString(new byte[0]); |
| final ByteString s4 = new ByteString(new byte[] {0}); |
| final ByteString s5 = new ByteString(new byte[]{15, 92}); |
| |
| // length |
| assertThat(s.length(), is(8)); |
| assertThat(s3.length(), is(0)); |
| assertThat(s4.length(), is(1)); |
| |
| // equals and hashCode |
| assertThat(s.hashCode(), is(s2.hashCode())); |
| assertThat(s.equals(s2), is(true)); |
| assertThat(s2.equals(s), is(true)); |
| assertThat(s.equals(s3), is(false)); |
| assertThat(s3.equals(s), is(false)); |
| |
| // toString |
| assertThat(s.toString(), is("030e0f5c00412300")); |
| assertThat(s3.toString(), is("")); |
| assertThat(s4.toString(), is("00")); |
| |
| // indexOf |
| assertThat(s.indexOf(s3), is(0)); |
| assertThat(s.indexOf(s3, 5), is(5)); |
| assertThat(s.indexOf(s3, 15), is(-1)); |
| assertThat(s.indexOf(s4), is(4)); |
| assertThat(s.indexOf(s4, 4), is(4)); |
| assertThat(s.indexOf(s4, 5), is(7)); |
| assertThat(s.indexOf(s5), is(2)); |
| assertThat(s.indexOf(s5, 2), is(2)); |
| assertThat(s.indexOf(s5, 3), is(-1)); |
| assertThat(s.indexOf(s5, 7), is(-1)); |
| |
| // substring |
| assertThat(s.substring(8), is(s3)); |
| assertThat(s.substring(7), is(s4)); |
| assertThat(s.substring(0), is(s)); |
| |
| // getBytes |
| assertThat(s.getBytes().length, is(8)); |
| assertThat(Arrays.equals(s.getBytes(), bytes), is(true)); |
| assertThat(s.getBytes()[3], is((byte) 92)); |
| final byte[] copyBytes = s.getBytes(); |
| copyBytes[3] = 11; |
| assertThat(s.getBytes()[3], is((byte) 92)); |
| assertThat(s, is(s2)); |
| } |
| |
| @Test public void testSkipFully() throws IOException { |
| InputStream in = of(""); |
| assertEquals(0, in.available()); |
| skipFully(in); |
| assertEquals(0, in.available()); |
| |
| in = of("asdf"); |
| assertEquals(4, in.available()); |
| skipFully(in); |
| assertEquals(0, in.available()); |
| |
| in = of("asdfasdf"); |
| for (int i = 0; i < 4; i++) { |
| assertNotEquals(-1, in.read()); |
| } |
| assertEquals(4, in.available()); |
| skipFully(in); |
| assertEquals(0, in.available()); |
| } |
| |
| /** Returns an InputStream of UTF-8 encoded bytes from the provided string */ |
| InputStream of(String str) { |
| return new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8)); |
| } |
| |
| /** Dummy implementation of {@link ConnectionProperty}. */ |
| private static class ConnectionPropertyImpl implements ConnectionProperty { |
| private final String name; |
| private final Object defaultValue; |
| private final Class<?> valueClass; |
| private Type type; |
| |
| ConnectionPropertyImpl(String name, Object defaultValue, Type type) { |
| this(name, defaultValue, type, null); |
| } |
| |
| ConnectionPropertyImpl(String name, Object defaultValue, Type type, |
| Class valueClass) { |
| this.name = name; |
| this.defaultValue = defaultValue; |
| this.type = type; |
| this.valueClass = type.deduceValueClass(defaultValue, valueClass); |
| if (!type.valid(defaultValue, this.valueClass)) { |
| throw new AssertionError(name); |
| } |
| } |
| |
| public String name() { |
| return name.toUpperCase(Locale.ROOT); |
| } |
| |
| public String camelName() { |
| return name.toLowerCase(Locale.ROOT); |
| } |
| |
| public Object defaultValue() { |
| return defaultValue; |
| } |
| |
| public Type type() { |
| return type; |
| } |
| |
| public Class valueClass() { |
| return valueClass; |
| } |
| |
| public ConnectionConfigImpl.PropEnv wrap(Properties properties) { |
| final HashMap<String, ConnectionProperty> map = new HashMap<>(); |
| map.put(name, this); |
| return new ConnectionConfigImpl.PropEnv( |
| ConnectionConfigImpl.parse(properties, map), this); |
| } |
| |
| public boolean required() { |
| return false; |
| } |
| } |
| |
| /** How large? */ |
| private enum Size { |
| BIG, |
| SMALL { |
| } |
| } |
| |
| /** How heavy? */ |
| private enum Weight { |
| HEAVY, LIGHT |
| } |
| } |
| |
| // End AvaticaUtilsTest.java |