This is an automated email from the ASF dual-hosted git repository. zabetak pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/calcite-avatica.git
commit efbf8a61e13277d4cbb292716d1473b81ebb61a7 Author: Alessandro Solimando <[email protected]> AuthorDate: Sat Feb 20 20:24:39 2021 +0100 Improve test coverage for float/real/double array types (Alessandro Solimando) 1. Add missing unit tests for CALCITE-3163 2. Reduce warnings in ArrayTypeTest.java 3. Refactor related code to improve readability Close apache/calcite-avatica#139 --- .../calcite/avatica/util/ArrayAccessorTest.java | 145 +++++++++++++ .../apache/calcite/avatica/util/ArrayImplTest.java | 134 +++++++----- .../calcite/avatica/util/AssertTestUtils.java | 76 +++++++ .../calcite/avatica/util/CursorTestUtils.java | 65 ++++++ .../calcite/avatica/remote/ArrayTypeTest.java | 231 ++++++++++++--------- 5 files changed, 499 insertions(+), 152 deletions(-) diff --git a/core/src/test/java/org/apache/calcite/avatica/util/ArrayAccessorTest.java b/core/src/test/java/org/apache/calcite/avatica/util/ArrayAccessorTest.java new file mode 100644 index 0000000..a9efc93 --- /dev/null +++ b/core/src/test/java/org/apache/calcite/avatica/util/ArrayAccessorTest.java @@ -0,0 +1,145 @@ +/* + * 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.util; + +import org.apache.calcite.avatica.ColumnMetaData; +import org.apache.calcite.avatica.ColumnMetaData.Rep; + +import org.apache.calcite.avatica.MetaImpl; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; + +import java.sql.Types; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertEquals; + +/** + * Test class for verifying functionality in array accessor from abstract cursor. + */ +@RunWith(Parameterized.class) +public class ArrayAccessorTest { + + private static final double DELTA = 1e-15; + private static final ArrayImpl.Factory ARRAY_FACTORY = + new ArrayFactoryImpl(Unsafe.localCalendar().getTimeZone()); + + private static final List<Function<List<List<Object>>, Cursor>> CURSOR_BUILDER = + Arrays.asList(CursorTestUtils::createArrayBasedCursor, + CursorTestUtils::createListBasedCursor); + + private Function<List<List<Object>>, Cursor> cursorBuilder; + + @Parameterized.Parameters + public static List<Object[]> parameters() throws Exception { + return CURSOR_BUILDER.stream() + .map(Collections::singletonList) + .map(List::toArray) + .collect(Collectors.toList()); + } + + public ArrayAccessorTest(Function<List<List<Object>>, Cursor> cursorBuilder) { + this.cursorBuilder = cursorBuilder; + } + + @Test public void listIteratorFromIntegerArray() throws Exception { + AssertTestUtils.Validator validator = + (Object o1, Object o2) -> assertEquals((int) o1, (int) o2); + + ColumnMetaData.ScalarType intType = ColumnMetaData.scalar(Types.INTEGER, "INTEGER", Rep.INTEGER); + + ColumnMetaData arrayMetadata = createArrayMetaData(intType); + + List<List<Object>> rowsValues = Arrays.asList(Arrays.asList(1, 2), + Collections.singletonList(3), Arrays.asList(4, 5, 6)); + + try (Cursor cursor = cursorBuilder.apply(rowsValues)) { + AssertTestUtils.assertRowsValuesMatchCursorContentViaArrayAccessor( + rowsValues, intType, cursor, arrayMetadata, ARRAY_FACTORY, validator); + } + } + + @Test public void resultSetFromRealArray() throws Exception { + AssertTestUtils.Validator validator = + (Object o1, Object o2) -> assertEquals((float) o1, (float) o2, DELTA); + + ColumnMetaData.ScalarType realType = ColumnMetaData.scalar(Types.REAL, "REAL", Rep.FLOAT); + + ColumnMetaData arrayMetadata = createArrayMetaData(realType); + + List<List<Object>> rowsValues = Arrays.asList( + Arrays.asList(1.123f, 0.2f), + Arrays.asList(4.1f, 5f, 66.12345f) + ); + + try (Cursor cursor = cursorBuilder.apply(rowsValues)) { + AssertTestUtils.assertRowsValuesMatchCursorContentViaArrayAccessor( + rowsValues, realType, cursor, arrayMetadata, ARRAY_FACTORY, validator); + } + } + + @Test public void resultSetFromDoubleArray() throws Exception { + AssertTestUtils.Validator validator = + (Object o1, Object o2) -> assertEquals((double) o1, (double) o2, DELTA); + + ColumnMetaData.ScalarType doubleType = ColumnMetaData.scalar(Types.DOUBLE, "DOUBLE", Rep.DOUBLE); + + ColumnMetaData arrayMetadata = createArrayMetaData(doubleType); + + List<List<Object>> rowsValues = Arrays.asList( + Arrays.asList(1.123d, 0.123456789012d), + Arrays.asList(4.134555d, 54444d, 66.12345d) + ); + + try (Cursor cursor = cursorBuilder.apply(rowsValues)) { + AssertTestUtils.assertRowsValuesMatchCursorContentViaArrayAccessor( + rowsValues, doubleType, cursor, arrayMetadata, ARRAY_FACTORY, validator); + } + } + + @Test public void resultSetFromFloatArray() throws Exception { + AssertTestUtils.Validator validator = + (Object o1, Object o2) -> assertEquals((double) o1, (double) o2, DELTA); + + ColumnMetaData.ScalarType floatType = ColumnMetaData.scalar(Types.FLOAT, "FLOAT", Rep.DOUBLE); + + ColumnMetaData arrayMetadata = createArrayMetaData(floatType); + + List<List<Object>> rowsValues = Arrays.asList( + Arrays.asList(1.123d, 0.123456789012d), + Arrays.asList(4.134555d, 54444d, 66.12345d) + ); + + try (Cursor cursor = cursorBuilder.apply(rowsValues)) { + AssertTestUtils.assertRowsValuesMatchCursorContentViaArrayAccessor( + rowsValues, floatType, cursor, arrayMetadata, ARRAY_FACTORY, validator); + } + } + + private static ColumnMetaData createArrayMetaData(ColumnMetaData.ScalarType componentType) { + ColumnMetaData.ArrayType arrayType = + ColumnMetaData.array(componentType, componentType.name, componentType.rep); + return MetaImpl.columnMetaData("MY_ARRAY", 1, arrayType, false); + } +} + +// End ArrayAccessorTest.java diff --git a/core/src/test/java/org/apache/calcite/avatica/util/ArrayImplTest.java b/core/src/test/java/org/apache/calcite/avatica/util/ArrayImplTest.java index 9133270..e2e4d9e 100644 --- a/core/src/test/java/org/apache/calcite/avatica/util/ArrayImplTest.java +++ b/core/src/test/java/org/apache/calcite/avatica/util/ArrayImplTest.java @@ -27,7 +27,6 @@ import org.apache.calcite.avatica.util.Cursor.Accessor; import org.junit.Test; import java.sql.Array; -import java.sql.ResultSet; import java.sql.Struct; import java.sql.Types; import java.util.Arrays; @@ -36,7 +35,6 @@ import java.util.List; import java.util.Objects; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; /** @@ -44,65 +42,81 @@ import static org.junit.Assert.assertTrue; */ public class ArrayImplTest { - @Test public void resultSetFromArray() throws Exception { - // Define the struct type we're creating + private static final double DELTA = 1e-15; + private static final ArrayImpl.Factory ARRAY_FACTORY = + new ArrayFactoryImpl(Unsafe.localCalendar().getTimeZone()); + + @Test public void resultSetFromIntegerArray() throws Exception { + AssertTestUtils.Validator validator = + (Object o1, Object o2) -> assertEquals((int) o1, (int) o2); + ScalarType intType = ColumnMetaData.scalar(Types.INTEGER, "INTEGER", Rep.INTEGER); - ArrayType arrayType = ColumnMetaData.array(intType, "INTEGER", Rep.INTEGER); - ColumnMetaData arrayMetaData = MetaImpl.columnMetaData("MY_ARRAY", 1, arrayType, false); - ArrayImpl.Factory factory = new ArrayFactoryImpl(Unsafe.localCalendar().getTimeZone()); - // Create some arrays from the structs - Array array1 = factory.createArray(intType, Arrays.<Object>asList(1, 2)); - Array array2 = factory.createArray(intType, Arrays.<Object>asList(3)); - Array array3 = factory.createArray(intType, Arrays.<Object>asList(4, 5, 6)); - List<List<Object>> rows = Arrays.asList(Collections.<Object>singletonList(array1), - Collections.<Object>singletonList(array2), Collections.<Object>singletonList(array3)); - // Create two rows, each with one (array) column - try (Cursor cursor = new ListIteratorCursor(rows.iterator())) { - List<Accessor> accessors = cursor.createAccessors(Collections.singletonList(arrayMetaData), - Unsafe.localCalendar(), factory); - assertEquals(1, accessors.size()); - Accessor accessor = accessors.get(0); + ColumnMetaData arrayMetadata = createArrayMetaData(intType); - assertTrue(cursor.next()); - Array actualArray = accessor.getArray(); - // An Array's result set has one row per array element. - // Each row has two columns. Column 1 is the array offset (1-based), Column 2 is the value. - ResultSet actualArrayResultSet = actualArray.getResultSet(); - assertEquals(2, actualArrayResultSet.getMetaData().getColumnCount()); - assertTrue(actualArrayResultSet.next()); - // Order is Avatica implementation specific - assertEquals(1, actualArrayResultSet.getInt(1)); - assertEquals(1, actualArrayResultSet.getInt(2)); - assertTrue(actualArrayResultSet.next()); - assertEquals(2, actualArrayResultSet.getInt(1)); - assertEquals(2, actualArrayResultSet.getInt(2)); - assertFalse(actualArrayResultSet.next()); + List<List<Object>> rowsValues = Arrays.asList(Arrays.asList(1, 2), + Collections.singletonList(3), Arrays.asList(4, 5, 6)); - assertTrue(cursor.next()); - actualArray = accessor.getArray(); - actualArrayResultSet = actualArray.getResultSet(); - assertEquals(2, actualArrayResultSet.getMetaData().getColumnCount()); - assertTrue(actualArrayResultSet.next()); - assertEquals(1, actualArrayResultSet.getInt(1)); - assertEquals(3, actualArrayResultSet.getInt(2)); - assertFalse(actualArrayResultSet.next()); + try (Cursor cursor = + CursorTestUtils.createArrayImplBasedCursor(rowsValues, intType, ARRAY_FACTORY)) { + AssertTestUtils.assertRowsValuesMatchCursorContentViaArrayAccessor( + rowsValues, intType, cursor, arrayMetadata, ARRAY_FACTORY, validator); + } + } - assertTrue(cursor.next()); - actualArray = accessor.getArray(); - actualArrayResultSet = actualArray.getResultSet(); - assertEquals(2, actualArrayResultSet.getMetaData().getColumnCount()); - assertTrue(actualArrayResultSet.next()); - assertEquals(1, actualArrayResultSet.getInt(1)); - assertEquals(4, actualArrayResultSet.getInt(2)); - assertTrue(actualArrayResultSet.next()); - assertEquals(2, actualArrayResultSet.getInt(1)); - assertEquals(5, actualArrayResultSet.getInt(2)); - assertTrue(actualArrayResultSet.next()); - assertEquals(3, actualArrayResultSet.getInt(1)); - assertEquals(6, actualArrayResultSet.getInt(2)); - assertFalse(actualArrayResultSet.next()); - - assertFalse(cursor.next()); + @Test public void resultSetFromRealArray() throws Exception { + AssertTestUtils.Validator validator = + (Object o1, Object o2) -> assertEquals((float) o1, (float) o2, DELTA); + + ScalarType realType = ColumnMetaData.scalar(Types.REAL, "REAL", Rep.FLOAT); + ColumnMetaData arrayMetadata = createArrayMetaData(realType); + + List<List<Object>> rowsValues = Arrays.asList( + Arrays.asList(1.123f, 0.2f), + Arrays.asList(4.1f, 5f, 66.12345f) + ); + + try (Cursor cursor = + CursorTestUtils.createArrayImplBasedCursor(rowsValues, realType, ARRAY_FACTORY)) { + AssertTestUtils.assertRowsValuesMatchCursorContentViaArrayAccessor( + rowsValues, realType, cursor, arrayMetadata, ARRAY_FACTORY, validator); + } + } + + @Test public void resultSetFromDoubleArray() throws Exception { + AssertTestUtils.Validator validator = + (Object o1, Object o2) -> assertEquals((double) o1, (double) o2, DELTA); + + ScalarType doubleType = ColumnMetaData.scalar(Types.DOUBLE, "DOUBLE", Rep.PRIMITIVE_DOUBLE); + ColumnMetaData arrayMetadata = createArrayMetaData(doubleType); + + List<List<Object>> rowsValues = Arrays.asList( + Arrays.asList(1.123d, 0.123456789012d), + Arrays.asList(4.134555d, 54444d, 66.12345d) + ); + + try (Cursor cursor = + CursorTestUtils.createArrayImplBasedCursor(rowsValues, doubleType, ARRAY_FACTORY)) { + AssertTestUtils.assertRowsValuesMatchCursorContentViaArrayAccessor( + rowsValues, doubleType, cursor, arrayMetadata, ARRAY_FACTORY, validator); + } + } + + @Test public void resultSetFromFloatArray() throws Exception { + AssertTestUtils.Validator validator = + (Object o1, Object o2) -> assertEquals((double) o1, (double) o2, DELTA); + + ScalarType floatType = ColumnMetaData.scalar(Types.FLOAT, "FLOAT", Rep.PRIMITIVE_DOUBLE); + ColumnMetaData arrayMetadata = createArrayMetaData(floatType); + + List<List<Object>> rowsValues = Arrays.asList( + Arrays.asList(1.123d, 0.123456789012d), + Arrays.asList(4.134555d, 54444d, 66.12345d) + ); + + try (Cursor cursor = + CursorTestUtils.createArrayImplBasedCursor(rowsValues, floatType, ARRAY_FACTORY)) { + AssertTestUtils.assertRowsValuesMatchCursorContentViaArrayAccessor( + rowsValues, floatType, cursor, arrayMetadata, ARRAY_FACTORY, validator); } } @@ -402,6 +416,12 @@ public class ArrayImplTest { assertEquals(5, data[1]); assertEquals(6, data[2]); } + + private static ColumnMetaData createArrayMetaData(ColumnMetaData.ScalarType componentType) { + ColumnMetaData.ArrayType arrayType = + ColumnMetaData.array(componentType, componentType.name, componentType.rep); + return MetaImpl.columnMetaData("MY_ARRAY", 1, arrayType, false); + } } // End ArrayImplTest.java diff --git a/core/src/test/java/org/apache/calcite/avatica/util/AssertTestUtils.java b/core/src/test/java/org/apache/calcite/avatica/util/AssertTestUtils.java new file mode 100644 index 0000000..ac2ba60 --- /dev/null +++ b/core/src/test/java/org/apache/calcite/avatica/util/AssertTestUtils.java @@ -0,0 +1,76 @@ +/* + * 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.util; + +import org.apache.calcite.avatica.ColumnMetaData; + +import java.sql.Array; +import java.sql.ResultSet; +import java.util.Collections; +import java.util.List; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +/** + * Utilities for assertions in tests of the util package. + */ +public class AssertTestUtils { + + private AssertTestUtils() { + // private constructor + } + + /** + * A simple interface to validate expected and actual values. + */ + interface Validator { + void validate(Object expected, Object actual); + } + + static void assertRowsValuesMatchCursorContentViaArrayAccessor( + List<List<Object>> rowsValues, ColumnMetaData.ScalarType arrayContentMetadata, + Cursor cursorOverArray, ColumnMetaData arrayMetaData, ArrayImpl.Factory factory, + Validator validator) throws Exception { + List<Cursor.Accessor> accessors = cursorOverArray.createAccessors( + Collections.singletonList(arrayMetaData), Unsafe.localCalendar(), factory); + assertEquals(1, accessors.size()); + Cursor.Accessor accessor = accessors.get(0); + + for (List<Object> rowValue : rowsValues) { + assertTrue(cursorOverArray.next()); + Array actualArray = accessor.getArray(); + // An Array's result set has one row per array element. + // Each row has two columns. Column 1 is the array offset (1-based), Column 2 is the value. + ResultSet actualArrayResultSet = actualArray.getResultSet(); + assertEquals(2, actualArrayResultSet.getMetaData().getColumnCount()); + assertEquals(arrayContentMetadata.id, actualArrayResultSet.getMetaData().getColumnType(2)); + assertTrue(actualArrayResultSet.next()); + + for (int j = 0; j < rowValue.size(); ++j) { + assertEquals(j + 1, actualArrayResultSet.getInt(1)); + // ResultSet.getObject() uses the column type internally, we can rely on that + validator.validate(rowValue.get(j), actualArrayResultSet.getObject(2)); + assertEquals(j < rowValue.size() - 1, actualArrayResultSet.next()); + } + } + assertFalse(cursorOverArray.next()); + } +} + +// End AssertTestUtils.java diff --git a/core/src/test/java/org/apache/calcite/avatica/util/CursorTestUtils.java b/core/src/test/java/org/apache/calcite/avatica/util/CursorTestUtils.java new file mode 100644 index 0000000..91278fb --- /dev/null +++ b/core/src/test/java/org/apache/calcite/avatica/util/CursorTestUtils.java @@ -0,0 +1,65 @@ +/* + * 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.util; + +import org.apache.calcite.avatica.ColumnMetaData; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Utilities methods for creating cursors from data for tests of the util package. + */ +public class CursorTestUtils { + + private CursorTestUtils() { + // private constructor + } + + static ListIteratorCursor createListBasedCursor(List<List<Object>> rowsValues) { + Iterator<List<Object>> iterator = rowsValues.stream() + .map(a -> (Object) a) + .map(Collections::singletonList) + .collect(Collectors.toList()) + .iterator(); + return new ListIteratorCursor(iterator); + } + + static ArrayIteratorCursor createArrayBasedCursor(List<List<Object>> rowsValues) { + Iterator<Object[]> iterator = Arrays.stream(rowsValues.toArray()) + .map(x -> Collections.singletonList(x).toArray()) + .iterator(); + return new ArrayIteratorCursor(iterator); + } + + static ListIteratorCursor createArrayImplBasedCursor( + List<List<Object>> rowsValues, ColumnMetaData.ScalarType arrayComponentType, + ArrayImpl.Factory factory) { + Iterator<List<Object>> iterator = rowsValues.stream() + .map(vals -> factory.createArray(arrayComponentType, vals)) + .map(a -> (Object) a) + .map(Collections::singletonList) + .collect(Collectors.toList()) + .iterator(); + return new ListIteratorCursor(iterator); + } +} + +// End CursorTestUtils.java diff --git a/server/src/test/java/org/apache/calcite/avatica/remote/ArrayTypeTest.java b/server/src/test/java/org/apache/calcite/avatica/remote/ArrayTypeTest.java index d73648d..d479a0a 100644 --- a/server/src/test/java/org/apache/calcite/avatica/remote/ArrayTypeTest.java +++ b/server/src/test/java/org/apache/calcite/avatica/remote/ArrayTypeTest.java @@ -92,9 +92,7 @@ public class ArrayTypeTest { } @AfterClass public static void afterClass() throws Exception { - if (null != SERVERS) { - SERVERS.stopServers(); - } + SERVERS.stopServers(); } @Test public void simpleArrayTest() throws Exception { @@ -155,7 +153,7 @@ public class ArrayTypeTest { if (0 == r.nextInt(2)) { value *= -1; } - elements.add(Short.valueOf(value)); + elements.add(value); } arrays.add(createArray("SMALLINT", component, elements)); } @@ -179,7 +177,7 @@ public class ArrayTypeTest { if (0 == r.nextInt(2)) { value *= -1; } - elements.add(Short.valueOf(value)); + elements.add(value); } elements.add(null); arrays.add(createArray("SMALLINT", component, elements)); @@ -266,7 +264,59 @@ public class ArrayTypeTest { } arrays.add(createArray("DOUBLE", component, elements)); } - writeAndReadArrays(conn, "float_arrays", "DOUBLE", component, arrays, + writeAndReadArrays(conn, "double_arrays", "DOUBLE", component, arrays, + PRIMITIVE_LIST_VALIDATOR); + } + } + + @Test public void realArrays() throws Exception { + final Random r = new Random(); + try (Connection conn = DriverManager.getConnection(url)) { + ScalarType component = ColumnMetaData.scalar(Types.REAL, "REAL", Rep.FLOAT); + List<Array> arrays = new ArrayList<>(); + // Construct the data + for (int i = 0; i < 3; i++) { + List<Float> elements = new ArrayList<>(); + for (int j = 0; j < 7; j++) { + float element = r.nextFloat(); + if (r.nextBoolean()) { + element *= -1; + } + elements.add(element); + } + arrays.add(createArray("REAL", component, elements)); + } + writeAndReadArrays(conn, "real_arrays", "REAL", component, arrays, + (expected, actual) -> { + // 'Real' maps to 'Float' following the JDBC specs, but hsqldb maps 'Double', 'Real' + // and 'Float' to Java 'double' + double[] expectedArray = Arrays.stream((Object[]) expected.getArray()) + .mapToDouble(x -> ((Float) x).doubleValue()).toArray(); + double[] actualArray = Arrays.stream((Object[]) actual.getArray()) + .mapToDouble(x -> (double) x).toArray(); + assertArrayEquals(expectedArray, actualArray, Double.MIN_VALUE); + }); + } + } + + @Test public void floatArrays() throws Exception { + final Random r = new Random(); + try (Connection conn = DriverManager.getConnection(url)) { + ScalarType component = ColumnMetaData.scalar(Types.FLOAT, "FLOAT", Rep.FLOAT); + List<Array> arrays = new ArrayList<>(); + // Construct the data + for (int i = 0; i < 3; i++) { + List<Double> elements = new ArrayList<>(); + for (int j = 0; j < 7; j++) { + double element = r.nextFloat(); + if (r.nextBoolean()) { + element *= -1; + } + elements.add(element); + } + arrays.add(createArray("FLOAT", component, elements)); + } + writeAndReadArrays(conn, "float_arrays", "FLOAT", component, arrays, PRIMITIVE_LIST_VALIDATOR); } } @@ -286,12 +336,13 @@ public class ArrayTypeTest { if (0 == r.nextInt(2)) { value *= -1; } - elements.add(Byte.valueOf(value)); + elements.add(value); } arrays.add(createArray("TINYINT", component, elements)); } // Verify read/write - writeAndReadArrays(conn, "byte_arrays", "TINYINT", component, arrays, BYTE_ARRAY_VALIDATOR); + writeAndReadArrays(conn, "byte_arrays", "TINYINT", component, arrays, + BYTE_ARRAY_VALIDATOR); } } @@ -326,35 +377,32 @@ public class ArrayTypeTest { } arrays.add(createArray("TIME", component, elements)); } - writeAndReadArrays(conn, "time_arrays", "TIME", component, arrays, new Validator<Array>() { - @Override public void validate(Array expected, Array actual) throws SQLException { - Object[] expectedTimes = (Object[]) expected.getArray(); - Object[] actualTimes = (Object[]) actual.getArray(); - assertEquals(expectedTimes.length, actualTimes.length); - final Calendar cal = Unsafe.localCalendar(); - for (int i = 0; i < expectedTimes.length; i++) { - cal.setTime((Time) expectedTimes[i]); - int expectedHour = cal.get(Calendar.HOUR_OF_DAY); - int expectedMinute = cal.get(Calendar.MINUTE); - int expectedSecond = cal.get(Calendar.SECOND); - cal.setTime((Time) actualTimes[i]); - assertEquals(expectedHour, cal.get(Calendar.HOUR_OF_DAY)); - assertEquals(expectedMinute, cal.get(Calendar.MINUTE)); - assertEquals(expectedSecond, cal.get(Calendar.SECOND)); - } - } - }); + writeAndReadArrays(conn, "time_arrays", "TIME", component, arrays, + (expected, actual) -> { + Object[] expectedTimes = (Object[]) expected.getArray(); + Object[] actualTimes = (Object[]) actual.getArray(); + assertEquals(expectedTimes.length, actualTimes.length); + final Calendar cal = Unsafe.localCalendar(); + for (int i = 0; i < expectedTimes.length; i++) { + cal.setTime((Time) expectedTimes[i]); + int expectedHour = cal.get(Calendar.HOUR_OF_DAY); + int expectedMinute = cal.get(Calendar.MINUTE); + int expectedSecond = cal.get(Calendar.SECOND); + cal.setTime((Time) actualTimes[i]); + assertEquals(expectedHour, cal.get(Calendar.HOUR_OF_DAY)); + assertEquals(expectedMinute, cal.get(Calendar.MINUTE)); + assertEquals(expectedSecond, cal.get(Calendar.SECOND)); + } + }); // Ensure an array with a null element can be written/read Array arrayWithNull = createArray("TIME", component, Arrays.asList((Time) null)); writeAndReadArrays(conn, "time_array_with_null", "TIME", component, - Collections.singletonList(arrayWithNull), new Validator<Array>() { - @Override public void validate(Array expected, Array actual) throws Exception { - Object[] expectedArray = (Object[]) expected.getArray(); - Object[] actualArray = (Object[]) actual.getArray(); - assertEquals(1, expectedArray.length); - assertEquals(expectedArray.length, actualArray.length); - assertEquals(expectedArray[0], actualArray[0]); - } + Collections.singletonList(arrayWithNull), (expected, actual) -> { + Object[] expectedArray = (Object[]) expected.getArray(); + Object[] actualArray = (Object[]) actual.getArray(); + assertEquals(1, expectedArray.length); + assertEquals(expectedArray.length, actualArray.length); + assertEquals(expectedArray[0], actualArray[0]); }); } } @@ -372,35 +420,32 @@ public class ArrayTypeTest { } arrays.add(createArray("DATE", component, elements)); } - writeAndReadArrays(conn, "date_arrays", "DATE", component, arrays, new Validator<Array>() { - @Override public void validate(Array expected, Array actual) throws SQLException { - Object[] expectedDates = (Object[]) expected.getArray(); - Object[] actualDates = (Object[]) actual.getArray(); - assertEquals(expectedDates.length, actualDates.length); - final Calendar cal = Unsafe.localCalendar(); - for (int i = 0; i < expectedDates.length; i++) { - cal.setTime((Date) expectedDates[i]); - int expectedDayOfMonth = cal.get(Calendar.DAY_OF_MONTH); - int expectedMonth = cal.get(Calendar.MONTH); - int expectedYear = cal.get(Calendar.YEAR); - cal.setTime((Date) actualDates[i]); - assertEquals(expectedDayOfMonth, cal.get(Calendar.DAY_OF_MONTH)); - assertEquals(expectedMonth, cal.get(Calendar.MONTH)); - assertEquals(expectedYear, cal.get(Calendar.YEAR)); - } - } - }); + writeAndReadArrays(conn, "date_arrays", "DATE", component, arrays, + (expected, actual) -> { + Object[] expectedDates = (Object[]) expected.getArray(); + Object[] actualDates = (Object[]) actual.getArray(); + assertEquals(expectedDates.length, actualDates.length); + final Calendar cal = Unsafe.localCalendar(); + for (int i = 0; i < expectedDates.length; i++) { + cal.setTime((Date) expectedDates[i]); + int expectedDayOfMonth = cal.get(Calendar.DAY_OF_MONTH); + int expectedMonth = cal.get(Calendar.MONTH); + int expectedYear = cal.get(Calendar.YEAR); + cal.setTime((Date) actualDates[i]); + assertEquals(expectedDayOfMonth, cal.get(Calendar.DAY_OF_MONTH)); + assertEquals(expectedMonth, cal.get(Calendar.MONTH)); + assertEquals(expectedYear, cal.get(Calendar.YEAR)); + } + }); // Ensure an array with a null element can be written/read Array arrayWithNull = createArray("DATE", component, Arrays.asList((Time) null)); writeAndReadArrays(conn, "date_array_with_null", "DATE", component, - Collections.singletonList(arrayWithNull), new Validator<Array>() { - @Override public void validate(Array expected, Array actual) throws Exception { - Object[] expectedArray = (Object[]) expected.getArray(); - Object[] actualArray = (Object[]) actual.getArray(); - assertEquals(1, expectedArray.length); - assertEquals(expectedArray.length, actualArray.length); - assertEquals(expectedArray[0], actualArray[0]); - } + Collections.singletonList(arrayWithNull), (expected, actual) -> { + Object[] expectedArray = (Object[]) expected.getArray(); + Object[] actualArray = (Object[]) actual.getArray(); + assertEquals(1, expectedArray.length); + assertEquals(expectedArray.length, actualArray.length); + assertEquals(expectedArray[0], actualArray[0]); }); } } @@ -420,43 +465,39 @@ public class ArrayTypeTest { arrays.add(createArray("TIMESTAMP", component, elements)); } writeAndReadArrays(conn, "timestamp_arrays", "TIMESTAMP", component, arrays, - new Validator<Array>() { - @Override public void validate(Array expected, Array actual) throws SQLException { - Object[] expectedTimestamps = (Object[]) expected.getArray(); - Object[] actualTimestamps = (Object[]) actual.getArray(); - assertEquals(expectedTimestamps.length, actualTimestamps.length); - final Calendar cal = Unsafe.localCalendar(); - for (int i = 0; i < expectedTimestamps.length; i++) { - cal.setTime((Timestamp) expectedTimestamps[i]); - int expectedDayOfMonth = cal.get(Calendar.DAY_OF_MONTH); - int expectedMonth = cal.get(Calendar.MONTH); - int expectedYear = cal.get(Calendar.YEAR); - int expectedHour = cal.get(Calendar.HOUR_OF_DAY); - int expectedMinute = cal.get(Calendar.MINUTE); - int expectedSecond = cal.get(Calendar.SECOND); - int expectedMillisecond = cal.get(Calendar.MILLISECOND); - cal.setTime((Timestamp) actualTimestamps[i]); - assertEquals(expectedDayOfMonth, cal.get(Calendar.DAY_OF_MONTH)); - assertEquals(expectedMonth, cal.get(Calendar.MONTH)); - assertEquals(expectedYear, cal.get(Calendar.YEAR)); - assertEquals(expectedHour, cal.get(Calendar.HOUR_OF_DAY)); - assertEquals(expectedMinute, cal.get(Calendar.MINUTE)); - assertEquals(expectedSecond, cal.get(Calendar.SECOND)); - assertEquals(expectedMillisecond, cal.get(Calendar.MILLISECOND)); - } + (expected, actual) -> { + Object[] expectedTimestamps = (Object[]) expected.getArray(); + Object[] actualTimestamps = (Object[]) actual.getArray(); + assertEquals(expectedTimestamps.length, actualTimestamps.length); + final Calendar cal = Unsafe.localCalendar(); + for (int i = 0; i < expectedTimestamps.length; i++) { + cal.setTime((Timestamp) expectedTimestamps[i]); + int expectedDayOfMonth = cal.get(Calendar.DAY_OF_MONTH); + int expectedMonth = cal.get(Calendar.MONTH); + int expectedYear = cal.get(Calendar.YEAR); + int expectedHour = cal.get(Calendar.HOUR_OF_DAY); + int expectedMinute = cal.get(Calendar.MINUTE); + int expectedSecond = cal.get(Calendar.SECOND); + int expectedMillisecond = cal.get(Calendar.MILLISECOND); + cal.setTime((Timestamp) actualTimestamps[i]); + assertEquals(expectedDayOfMonth, cal.get(Calendar.DAY_OF_MONTH)); + assertEquals(expectedMonth, cal.get(Calendar.MONTH)); + assertEquals(expectedYear, cal.get(Calendar.YEAR)); + assertEquals(expectedHour, cal.get(Calendar.HOUR_OF_DAY)); + assertEquals(expectedMinute, cal.get(Calendar.MINUTE)); + assertEquals(expectedSecond, cal.get(Calendar.SECOND)); + assertEquals(expectedMillisecond, cal.get(Calendar.MILLISECOND)); } }); // Ensure an array with a null element can be written/read Array arrayWithNull = createArray("TIMESTAMP", component, Arrays.asList((Timestamp) null)); writeAndReadArrays(conn, "timestamp_array_with_null", "TIMESTAMP", component, - Collections.singletonList(arrayWithNull), new Validator<Array>() { - @Override public void validate(Array expected, Array actual) throws Exception { - Object[] expectedArray = (Object[]) expected.getArray(); - Object[] actualArray = (Object[]) actual.getArray(); - assertEquals(1, expectedArray.length); - assertEquals(expectedArray.length, actualArray.length); - assertEquals(expectedArray[0], actualArray[0]); - } + Collections.singletonList(arrayWithNull), (expected, actual) -> { + Object[] expectedArray = (Object[]) expected.getArray(); + Object[] actualArray = (Object[]) actual.getArray(); + assertEquals(1, expectedArray.length); + assertEquals(expectedArray.length, actualArray.length); + assertEquals(expectedArray[0], actualArray[0]); }); } } @@ -547,8 +588,8 @@ public class ArrayTypeTest { List<ColumnMetaData> types = Collections.singletonList(ColumnMetaData.dummy(array, true)); Calendar calendar = Unsafe.localCalendar(); List<Accessor> accessors = cursor.createAccessors(types, calendar, null); - assertTrue("Expected at least one accessor, found " + accessors.size(), - !accessors.isEmpty()); + assertFalse("Expected at least one accessor, found " + accessors.size(), + accessors.isEmpty()); ArrayAccessor arrayAccessor = (ArrayAccessor) accessors.get(0); return new ArrayImpl((List<Object>) arrayValues, arrayAccessor); @@ -620,7 +661,7 @@ public class ArrayTypeTest { private static final PrimitiveArrayValidator PRIMITIVE_LIST_VALIDATOR = new PrimitiveArrayValidator(); /** - * Validator that coerces primitive arrays into lists and comparse them. + * Validator that coerces primitive arrays into lists and compare them. */ private static class PrimitiveArrayValidator implements Validator<Array> { @Override public void validate(Array expected, Array actual) throws SQLException {
