blob: 178c2910198cdaf20f3455f4f4d5b198f2487553 [file] [log] [blame]
/*
* 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.cassandra.db.marshal;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import org.junit.Assert;
import org.junit.Test;
import org.apache.cassandra.cql3.FieldIdentifier;
import org.apache.cassandra.utils.ByteBufferUtil;
import static org.apache.cassandra.db.marshal.ValueAccessors.ACCESSORS;
public class CompositeAndTupleTypesTest
{
interface TypeFactory<T extends AbstractType> { T createType(List<AbstractType<?>> types); }
interface ValueCombiner<V> { V combine(ValueAccessor<V> accessor, V[] values); }
public static Object[] createValues(ValueGenerator[] generators, Random random)
{
Object[] values = new Object[generators.length];
for (int i=0; i<generators.length; i++)
values[i] = generators[i].nextValue(random);
return values;
}
public static ByteBuffer[] decompose(ValueGenerator[] generators, Object[] values)
{
assert generators.length == values.length;
ByteBuffer[] decomposed = new ByteBuffer[generators.length];
for (int i=0; i<generators.length; i++)
{
decomposed[i] = ((AbstractType<Object>) generators[i].getType()).decompose(values[i]);
}
return decomposed;
}
public static <S, D> D[] convert(S[] src, ValueAccessor<S> srcAccessor, ValueAccessor<D> dstAccessor)
{
D[] dst = dstAccessor.createArray(src.length);
for (int i=0; i<src.length; i++)
dst[i] = dstAccessor.convert(src[i], srcAccessor);
return dst;
}
public static <V> Object[] compose(ValueGenerator[] generators, V[] values, ValueAccessor<V> accessor)
{
assert generators.length == values.length;
Object[] composed = new Object[generators.length];
for (int i=0; i<generators.length; i++)
{
composed[i] = ((AbstractType<Object>) generators[i].getType()).compose(values[i], accessor);
}
return composed;
}
public <AT extends AbstractType> void testSerializationDeserialization(TypeFactory<AT> typeFactory, ValueCombiner combiner)
{
for (int i=0; i<100; i++)
{
Random random = new Random(i);
ValueGenerator[] generators = ValueGenerator.randomGenerators(random, 100);
AT type = typeFactory.createType(ValueGenerator.toTypes(generators));
for (int j=0; j<100; j++)
{
Object[] expected = createValues(generators, random);
for (ValueAccessor<Object> srcAccessor : ACCESSORS)
{
ByteBuffer[] srcBuffers = decompose(generators, expected);
Object[] srcValues = convert(srcBuffers, ByteBufferAccessor.instance, srcAccessor);
Object srcJoined = combiner.combine(srcAccessor, srcValues);
String srcString = type.getString(srcJoined, srcAccessor);
for (ValueAccessor<Object> dstAccessor : ACCESSORS)
{
// convert data types and deserialize with
Object[] dstValues = convert(srcValues, srcAccessor, dstAccessor);
Object dstJoined = combiner.combine(dstAccessor, dstValues);
String dstString = type.getString(dstJoined, dstAccessor);
Object[] composed = compose(generators, dstValues, dstAccessor);
Assert.assertArrayEquals(expected, composed);
ValueAccessors.assertDataEquals(srcJoined, srcAccessor, dstJoined, dstAccessor);
Assert.assertEquals(srcString, dstString);
}
}
}
}
}
@Test
public void tuple()
{
testSerializationDeserialization(TupleType::new, TupleType::buildValue);
}
@Test
public void userType()
{
TypeFactory<UserType> factory = types -> {
List<FieldIdentifier> names = new ArrayList<>(types.size());
for (int i=0; i<types.size(); i++)
{
names.add(FieldIdentifier.forUnquoted("t" + i));
}
return new UserType("ks", ByteBufferUtil.bytes("user_type"), names, types, false);
};
testSerializationDeserialization(factory, TupleType::buildValue);
}
@Test
public void composite()
{
testSerializationDeserialization(CompositeType::new, CompositeType::build);
}
}