/** * Copyright (C) 2014-2017 Xavier Witdouck * * 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 com.zavtech.morpheus.array; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.Month; import java.time.ZoneId; import java.time.ZonedDateTime; import java.util.Calendar; import java.util.Currency; import java.util.Date; import java.util.Random; import java.util.TimeZone; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; import com.zavtech.morpheus.range.Range; import org.testng.Assert; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; /** * Unit tests for the ArrayBuilder class. * * @author Xavier Witdouck * * <p><strong>This is open source software released under the <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a></strong></p> */ public class ArrayBuilderTests { @DataProvider(name = "sizes") public Object[][] sizes() { return new Object[][] {{0}, {7}, {100}, {5000}}; } @DataProvider(name = "types") public Object[][] types() { return new Object[][] { { Object.class }, { Boolean.class }, { Integer.class }, { Long.class }, { Double.class }, { String.class }, { Month.class }, { Currency.class }, { Date.class }, { LocalDate.class }, { LocalTime.class }, { LocalDateTime.class }, { ZonedDateTime.class } }; } @Test() public void testEmpty() { final ArrayBuilder<Boolean> builder = ArrayBuilder.of(10); final Array<Boolean> empty = builder.toArray(); Assert.assertTrue(empty.length() == 0, "The array is zero length"); Assert.assertTrue(empty.typeCode() == ArrayType.OBJECT); } @Test(dataProvider = "types") public void testEmptyWithType(Class<?> type) { final ArrayBuilder<?> builder = ArrayBuilder.of(10, type); final Array<?> empty = builder.toArray(); Assert.assertTrue(empty.length() == 0, "The array is zero length"); Assert.assertTrue(empty.typeCode() == ArrayType.of(type), "The array types match"); } @Test() public void testWhenExpansionRequired() { final ArrayBuilder<Double> builder = ArrayBuilder.of(10, Double.class); Range.of(0, 101).forEach(i -> builder.addDouble(Math.random())); final Array<Double> array = builder.toArray(); Assert.assertEquals(array.length(), 101, "Array length matches expected"); } @Test() public void testWhenContractionRequired() { final ArrayBuilder<Double> builder = ArrayBuilder.of(1000, Double.class); Range.of(0, 101).forEach(i -> builder.addDouble(Math.random())); final Array<Double> array = builder.toArray(); Assert.assertEquals(array.length(), 101, "Array length matches expected"); } @Test(dataProvider = "sizes") public void testWithBooleans(int initialSize) { final Random random = new Random(); final ArrayBuilder<Boolean> builder = ArrayBuilder.of(initialSize); final boolean[] expected = new boolean[1000]; for (int i=0; i<expected.length; ++i) { expected[i] = random.nextBoolean(); builder.add(expected[i]); } final Array<Boolean> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.BOOLEAN, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getBoolean(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithIntegers(int initialSize) { final Random random = new Random(); final ArrayBuilder<Integer> builder = ArrayBuilder.of(initialSize); final int[] expected = new int[1000]; for (int i=0; i<expected.length; ++i) { expected[i] = random.nextInt(); builder.add(expected[i]); } final Array<Integer> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.INTEGER, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getInt(i), expected[i], "The values match at " + i); } final Array<Integer> collected = IntStream.of(expected).boxed().collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getInt(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithLongs(int initialSize) { final Random random = new Random(); final ArrayBuilder<Long> builder = ArrayBuilder.of(initialSize); final long[] expected = new long[1000]; for (int i=0; i<expected.length; ++i) { expected[i] = random.nextLong(); builder.add(expected[i]); } final Array<Long> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.LONG, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getLong(i), expected[i], "The values match at " + i); } final Array<Long> collected = LongStream.of(expected).boxed().collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getLong(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithDoubles(int initialSize) { final Random random = new Random(); final ArrayBuilder<Double> builder = ArrayBuilder.of(initialSize); final double[] expected = new double[1000]; for (int i=0; i<expected.length; ++i) { expected[i] = random.nextDouble(); builder.add(expected[i]); } final Array<Double> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.DOUBLE, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getDouble(i), expected[i], "The values match at " + i); } final Array<Double> collected = DoubleStream.of(expected).boxed().collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getDouble(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithStrings(int initialSize) { final Random random = new Random(); final ArrayBuilder<String> builder = ArrayBuilder.of(initialSize); final String[] expected = new String[1000]; for (int i=0; i<expected.length; ++i) { expected[i] = "X=" + random.nextDouble(); builder.add(expected[i]); } final Array<String> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.STRING, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<String> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithDates(int initialSize) { final ArrayBuilder<Date> builder = ArrayBuilder.of(initialSize); final Date[] expected = new Date[1000]; final Calendar calender = Calendar.getInstance(); for (int i=0; i<expected.length; ++i) { calender.add(Calendar.DATE, 1); expected[i] = calender.getTime(); builder.add(expected[i]); } final Array<Date> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.DATE, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<Date> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithCurrencies(int initialSize) { final ArrayBuilder<Currency> builder = ArrayBuilder.of(initialSize); final Currency[] expected = Currency.getAvailableCurrencies().stream().toArray(Currency[]::new); for (Currency exp : expected) { builder.add(exp); } final Array<Currency> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.CURRENCY, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<Currency> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithTimeZones(int initialSize) { final ArrayBuilder<TimeZone> builder = ArrayBuilder.of(initialSize); final TimeZone[] expected = Stream.of(TimeZone.getAvailableIDs()).map(TimeZone::getTimeZone).toArray(TimeZone[]::new); for (TimeZone exp : expected) { builder.add(exp); } final Array<TimeZone> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.TIME_ZONE, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<TimeZone> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithZonedIds(int initialSize) { final ArrayBuilder<ZoneId> builder = ArrayBuilder.of(initialSize); final ZoneId[] expected = ZoneId.getAvailableZoneIds().stream().map(ZoneId::of).toArray(ZoneId[]::new); for (ZoneId exp : expected) { builder.add(exp); } final Array<ZoneId> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.ZONE_ID, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<ZoneId> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithLocalDates(int initialSize) { final ArrayBuilder<LocalDate> builder = ArrayBuilder.of(initialSize); final LocalDate[] expected = new LocalDate[1000]; for (int i=0; i<expected.length; ++i) { expected[i] = LocalDate.now().plusDays(i); builder.add(expected[i]); } final Array<LocalDate> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.LOCAL_DATE, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<LocalDate> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithLocalTimes(int initialSize) { final ArrayBuilder<LocalTime> builder = ArrayBuilder.of(initialSize); final LocalTime[] expected = new LocalTime[1000]; for (int i=0; i<expected.length; ++i) { expected[i] = LocalTime.now().plusMinutes(i); builder.add(expected[i]); } final Array<LocalTime> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.LOCAL_TIME, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<LocalTime> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithLocalDateTimes(int initialSize) { final ArrayBuilder<LocalDateTime> builder = ArrayBuilder.of(initialSize); final LocalDateTime[] expected = new LocalDateTime[1000]; for (int i=0; i<expected.length; ++i) { expected[i] = LocalDateTime.now().plusMinutes(i); builder.add(expected[i]); } final Array<LocalDateTime> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.LOCAL_DATETIME, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<LocalDateTime> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithZonedDateTimes(int initialSize) { final ArrayBuilder<ZonedDateTime> builder = ArrayBuilder.of(initialSize); final ZonedDateTime[] expected = new ZonedDateTime[1000]; for (int i=0; i<expected.length; ++i) { expected[i] = ZonedDateTime.now().plusMinutes(i); builder.add(expected[i]); } final Array<ZonedDateTime> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.ZONED_DATETIME, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<ZonedDateTime> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test(dataProvider = "sizes") public void testWithMixedTypes(int initialSize) { final Random random = new Random(); final ArrayBuilder<Object> builder = ArrayBuilder.of(initialSize); final Object[] expected = new Object[1000]; for (int i=0; i<100; ++i) { expected[i] = ZonedDateTime.now().plusMinutes(i); builder.add(expected[i]); } for (int i=100; i<200; ++i) { expected[i] = random.nextDouble(); builder.add(expected[i]); } for (int i=200; i<300; ++i) { expected[i] = random.nextLong(); builder.add(expected[i]); } for (int i=300; i<400; ++i) { expected[i] = random.nextInt(); builder.add(expected[i]); } for (int i=400; i<1000; ++i) { expected[i] = random.nextBoolean(); builder.add(expected[i]); } final Array<Object> actual = builder.toArray(); Assert.assertEquals(actual.length(), expected.length, "The lengths match"); Assert.assertEquals(actual.typeCode(), ArrayType.OBJECT, "The array type is as expected"); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(actual.getValue(i), expected[i], "The values match at " + i); } final Array<Object> collected = Stream.of(expected).collect(ArrayUtils.toArray(expected.length)); for (int i=0; i<expected.length; ++i) { Assert.assertEquals(collected.getValue(i), expected[i], "The values match at " + i); } } @Test() public void testConcat() { final ArrayBuilder<Double> builder1 = ArrayBuilder.of(20); final ArrayBuilder<Double> builder2 = ArrayBuilder.of(20); final Array<Double> array1 = Range.of(0, 1000).map(i -> Math.random()).toArray(); final Array<Double> array2 = Range.of(0, 768).map(i -> Math.random()).toArray(); Assert.assertEquals(array1.length(), 1000); Assert.assertEquals(array2.length(), 768); array1.forEachValue(v -> builder1.addDouble(v.getDouble())); array2.forEachValue(v -> builder2.addDouble(v.getDouble())); final Array<Double> combined = builder1.addAll(builder2).toArray(); Assert.assertEquals(combined.length(), array1.length() + array2.length()); for (int i=0; i<array1.length(); ++i) { final double v1 = array1.getDouble(i); final double v2 = combined.getDouble(i); Assert.assertEquals(v2, v1, "Values match at index " + i); } for (int i=0; i<array2.length(); ++i) { final double v1 = array2.getDouble(i); final double v2 = combined.getDouble(i + array1.length()); Assert.assertEquals(v2, v1, "Values match at index " + i); } } @Test() public void testCollector1() { final Array<Integer> array1 = IntStream.range(0, 1000).boxed().collect(ArrayUtils.toArray(100)); final Array<Integer> array2 = IntStream.range(0, 1000).boxed().collect(ArrayUtils.toArray(Integer.class, 100)); final Array<Integer> array3 = IntStream.range(0, 1000).boxed().collect(ArrayUtils.toArray(Integer.class, 100)); Assert.assertEquals(array1, array2); Assert.assertEquals(array1, array3); } }