/*
* Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
* license agreements. See the NOTICE file distributed with this work for
* additional information regarding copyright ownership. Crate 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.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial agreement.
*/
package io.crate.types;
import io.crate.test.integration.CrateUnitTest;
import org.junit.Test;
import java.util.Arrays;
import java.util.Iterator;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.LongAdder;
import static org.hamcrest.core.Is.is;
public class TypeConversionTest extends CrateUnitTest {
private static class Repeater<T> implements Iterable<T>, Iterator<T> {
private final LongAdder repeated;
private final Callable<T> repeatMe;
public Repeater(Callable<T> repeatMe, long times) {
this.repeated = new LongAdder();
this.repeated.add(times);
this.repeatMe = repeatMe;
}
@Override
public Iterator<T> iterator() {
return this;
}
@Override
public boolean hasNext() {
return repeated.longValue() > 0;
}
@Override
public T next() {
repeated.decrement();
try {
return repeatMe.call();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Override
public void remove() {
// ignore
}
}
private Iterable<Byte> bytes(int num) {
return new Repeater<>(new Callable<Byte>() {
@Override
public Byte call() throws Exception {
return randomByte();
}
}, num);
}
private Iterable<Integer> integers(final int lower, final int upper, int num) {
return new Repeater<>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return randomIntBetween(lower, upper);
}
}, num);
}
@Test
public void numberConversionTest() throws Exception {
for (Byte byteVal : bytes(10)) {
for (DataType t : DataTypes.ALLOWED_CONVERSIONS.get(DataTypes.BYTE.id())) {
if (t.equals(DataTypes.IP)) {
byteVal = (byte) Math.abs(byteVal == Byte.MIN_VALUE ? byteVal >> 1 : byteVal);
}
t.value(byteVal);
}
}
for (Integer shortVal : integers((int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 10)) {
for (DataType t : DataTypes.ALLOWED_CONVERSIONS.get(DataTypes.SHORT.id())) {
shortVal = t.equals(DataTypes.IP) ? Math.abs(shortVal) : shortVal;
t.value(shortVal.shortValue());
}
}
for (Integer intValue : integers((int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 10)) {
for (DataType t : DataTypes.ALLOWED_CONVERSIONS.get(DataTypes.INTEGER.id())) {
intValue = t.equals(DataTypes.IP) ? Math.abs(intValue) : intValue;
t.value(intValue);
}
}
for (Integer longValue : integers((int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 10)) {
for (DataType t : DataTypes.ALLOWED_CONVERSIONS.get(DataTypes.LONG.id())) {
longValue = t.equals(DataTypes.IP) ? Math.abs(longValue) : longValue;
t.value(longValue.longValue());
}
}
for (Integer floatValue : integers((int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 10)) {
for (DataType t : DataTypes.ALLOWED_CONVERSIONS.get(DataTypes.FLOAT.id())) {
floatValue = t.equals(DataTypes.IP) ? Math.abs(floatValue) : floatValue;
t.value(floatValue.floatValue());
}
}
for (Integer doubleValue : integers((int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, 10)) {
for (DataType t : DataTypes.ALLOWED_CONVERSIONS.get(DataTypes.DOUBLE.id())) {
doubleValue = t.equals(DataTypes.IP) ? Math.abs(doubleValue) : doubleValue;
t.value(doubleValue.doubleValue());
}
}
}
@Test(expected = IllegalArgumentException.class)
public void testByteOutOfRangeNegative() throws Exception {
DataTypes.BYTE.value(-129);
}
@Test(expected = IllegalArgumentException.class)
public void testByteOutOfRangePositive() throws Exception {
DataTypes.BYTE.value(129);
}
@Test(expected = IllegalArgumentException.class)
public void testShortOutOfRangePositive() throws Exception {
DataTypes.SHORT.value(Integer.MAX_VALUE);
}
@Test(expected = IllegalArgumentException.class)
public void testShortOutOfRangeNegative() throws Exception {
DataTypes.SHORT.value(Integer.MIN_VALUE);
}
@Test(expected = IllegalArgumentException.class)
public void testIntOutOfRangePositive() throws Exception {
DataTypes.INTEGER.value(Long.MAX_VALUE);
}
@Test(expected = IllegalArgumentException.class)
public void testIntOutOfRangeNegative() throws Exception {
DataTypes.INTEGER.value(Long.MIN_VALUE);
}
@Test(expected = IllegalArgumentException.class)
public void testFloatOutOfRangePositive() throws Exception {
DataTypes.FLOAT.value(Double.MAX_VALUE);
}
@Test(expected = IllegalArgumentException.class)
public void testFloatOutOfRangenegative() throws Exception {
DataTypes.FLOAT.value(-Double.MAX_VALUE);
}
@Test(expected = IllegalArgumentException.class)
public void testIpNegativeValue() throws Exception {
DataTypes.IP.value(Long.MIN_VALUE);
}
@Test
public void selfConversionTest() throws Exception {
for (DataType type : com.google.common.collect.Iterables.concat(
DataTypes.PRIMITIVE_TYPES,
Arrays.asList(DataTypes.UNDEFINED, DataTypes.GEO_POINT, DataTypes.GEO_SHAPE, DataTypes.OBJECT))) {
assertTrue(type.isConvertableTo(type));
ArrayType arrayType = new ArrayType(type);
assertTrue(arrayType.isConvertableTo(arrayType));
SetType setType = new SetType(type);
assertTrue(setType.isConvertableTo(setType));
}
}
@Test
public void testNotSupportedConversion() throws Exception {
for (DataType type : com.google.common.collect.Iterables.concat(
DataTypes.PRIMITIVE_TYPES,
Arrays.asList(DataTypes.GEO_POINT, DataTypes.GEO_SHAPE, DataTypes.OBJECT))) {
assertFalse(DataTypes.NOT_SUPPORTED.isConvertableTo(type));
}
}
@Test
public void testToNullConversions() throws Exception {
for (DataType type : com.google.common.collect.Iterables.concat(
DataTypes.PRIMITIVE_TYPES,
Arrays.asList(DataTypes.GEO_POINT, DataTypes.GEO_SHAPE, DataTypes.OBJECT))) {
assertThat(type.isConvertableTo(DataTypes.UNDEFINED), is(false));
}
assertThat(DataTypes.UNDEFINED.isConvertableTo(DataTypes.UNDEFINED), is(true));
}
@Test
public void testGeoPointConversion() throws Exception {
assertThat(DataTypes.GEO_POINT.isConvertableTo(new ArrayType(DataTypes.DOUBLE)), is(true));
assertThat(DataTypes.STRING.isConvertableTo(DataTypes.GEO_POINT), is(true));
}
@Test
public void testGeoShapeConversion() throws Exception {
assertThat(DataTypes.STRING.isConvertableTo(DataTypes.GEO_SHAPE), is(true));
assertThat(DataTypes.OBJECT.isConvertableTo(DataTypes.GEO_SHAPE), is(true));
}
}