/*
* Written by Gil Tene and Martin Thompson, and released to the public domain,
* as explained at http://creativecommons.org/publicdomain/zero/1.0/
*/
package org.ObjectLayoutApiTests;
import org.ObjectLayout.*;
import org.junit.Test;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import static java.lang.Long.valueOf;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class StructuredArrayTest {
static final MethodHandles.Lookup lookup = MethodHandles.lookup();
@Test
public void shouldConstructArrayOfGivenDirectLengths() throws NoSuchMethodException {
final long[] lengths = {7L, 8L, 9L};
@SuppressWarnings("unchecked")
final StructuredArray<StructuredArray<StructuredArray<MockStructure>>> array =
new StructuredArrayBuilder(
StructuredArray.class,
new StructuredArrayBuilder(
StructuredArray.class,
new StructuredArrayBuilder(
lookup,
StructuredArray.class,
MockStructure.class,
lengths[2]
),
lengths[1]
),
lengths[0]
).build();
assertThat(valueOf(array.getLength()), is(lengths[0]));
assertThat(valueOf(array.get(0).getLength()), is(lengths[1]));
assertThat(valueOf(array.get(0).get(0).getLength()), is(lengths[2]));
assertTrue(array.getElementClass().isAssignableFrom(StructuredArray.class));
assertTrue(array.get(0).getElementClass().isAssignableFrom(StructuredArray.class));
assertTrue(array.get(0).get(0).getElementClass() == MockStructure.class);
}
@Test
public void shouldConstructArrayOfGivenDirectLengthsPublic() throws NoSuchMethodException {
final long[] lengths = {7L, 8L, 9L};
@SuppressWarnings("unchecked")
StructuredArray<StructuredArray<StructuredArray<PublicMockStructure>>> array =
new StructuredArrayBuilder(
StructuredArray.class,
new StructuredArrayBuilder(
StructuredArray.class,
new StructuredArrayBuilder(
StructuredArray.class,
PublicMockStructure.class,
lengths[2]
),
lengths[1]
),
lengths[0]
).build();
assertThat(valueOf(array.getLength()), is(lengths[0]));
assertThat(valueOf(array.get(0).getLength()), is(lengths[1]));
assertThat(valueOf(array.get(0).get(0).getLength()), is(lengths[2]));
assertTrue(array.getElementClass().isAssignableFrom(StructuredArray.class));
assertTrue(array.get(0).getElementClass().isAssignableFrom(StructuredArray.class));
assertTrue(array.get(0).get(0).getElementClass() == PublicMockStructure.class);
}
@Test
public void shouldConstructArrayOfGivenLengthWithNewInstance() throws NoSuchMethodException {
long length = 9L;
StructuredArray<MockStructure> array = StructuredArray.newInstance(lookup, MockStructure.class, length);
assertThat(valueOf(array.getLength()), is(valueOf(length)));
assertTrue(array.getElementClass() == MockStructure.class);
}
@Test
public void shouldConstructArrayOfGivenLengthWithNewInstancePublic() throws NoSuchMethodException {
long length = 9L;
StructuredArray<PublicMockStructure> array = StructuredArray.newInstance(PublicMockStructure.class, length);
assertThat(valueOf(array.getLength()), is(valueOf(length)));
assertTrue(array.getElementClass() == PublicMockStructure.class);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilder() throws NoSuchMethodException {
long length = 9L;
@SuppressWarnings("unchecked")
StructuredArray<MockStructure> array =
new StructuredArrayBuilder(
lookup,
StructuredArray.class,
MockStructure.class,
length).
build();
assertThat(valueOf(array.getLength()), is(valueOf(length)));
assertTrue(array.getElementClass() == MockStructure.class);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderPublic() throws NoSuchMethodException {
long length = 9L;
@SuppressWarnings("unchecked")
StructuredArray<PublicMockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
PublicMockStructure.class,
length).
build();
assertThat(valueOf(array.getLength()), is(valueOf(length)));
assertTrue(array.getElementClass() == PublicMockStructure.class);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgs() throws NoSuchMethodException, IllegalAccessException {
final Class[] initArgTypes = {long.class, long.class};
final long expectedIndex = 4L;
final long expectedValue = 777L;
long length = 9L;
final CtorAndArgs<MockStructure> ctorAndArgs =
new CtorAndArgs<MockStructure>(lookup, MockStructure.class, initArgTypes, expectedIndex, expectedValue);
@SuppressWarnings("unchecked")
StructuredArray<MockStructure> array =
new StructuredArrayBuilder(
lookup,
StructuredArray.class,
MockStructure.class,
length).
elementCtorAndArgs(ctorAndArgs).
build();
assertCorrectFixedInitialisation(expectedIndex, expectedValue, new long[]{length}, array);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgsPublic() throws NoSuchMethodException {
final Class[] initArgTypes = {long.class, long.class};
final long expectedIndex = 4L;
final long expectedValue = 777L;
long length = 9L;
final CtorAndArgs<PublicMockStructure> ctorAndArgs =
new CtorAndArgs<PublicMockStructure>(PublicMockStructure.class, initArgTypes, expectedIndex, expectedValue);
@SuppressWarnings("unchecked")
StructuredArray<PublicMockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
PublicMockStructure.class,
length).
elementCtorAndArgs(ctorAndArgs).
build();
assertCorrectFixedInitialisation(expectedIndex, expectedValue, new long[] {length}, array);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgs2() throws NoSuchMethodException {
final long expectedIndex = 4L;
final long expectedValue = 777L;
long length = 9L;
final Constructor<MockStructure> constructor = MockStructure.class.getConstructor(long.class, long.class);
constructor.setAccessible(true); // When constructor is passed in, setAccessible is the caller responsibility...
@SuppressWarnings("unchecked")
StructuredArray<MockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
MockStructure.class,
length).
elementCtorAndArgs(constructor, expectedIndex, expectedValue).
build();
assertCorrectFixedInitialisation(expectedIndex, expectedValue, new long[] {length}, array);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgs2Public() throws NoSuchMethodException {
final long expectedIndex = 4L;
final long expectedValue = 777L;
long length = 9L;
final Constructor<PublicMockStructure> constructor =
PublicMockStructure.class.getConstructor(long.class, long.class);
@SuppressWarnings("unchecked")
StructuredArray<PublicMockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
PublicMockStructure.class,
length).
elementCtorAndArgs(constructor, expectedIndex, expectedValue).
build();
assertCorrectFixedInitialisation(expectedIndex, expectedValue, new long[] {length}, array);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgsProvider() throws NoSuchMethodException {
long length = 9L;
final Constructor<MockStructure> constructor = MockStructure.class.getConstructor(long.class, long.class);
constructor.setAccessible(true); // When constructor is passed in, setAccessible is the caller responsibility...
@SuppressWarnings("unchecked")
StructuredArray<MockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
MockStructure.class,
length).
elementCtorAndArgsProvider(
new CtorAndArgsProvider() {
@Override
public CtorAndArgs getForContext(
ConstructionContext context) throws NoSuchMethodException {
return new CtorAndArgs(constructor, context.getIndex(), context.getIndex() * 2);
}
}
).
build();
assertCorrectVariableInitialisation(new long[]{length}, array);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgsProviderPublic() throws NoSuchMethodException {
long length = 9L;
final Constructor<PublicMockStructure> constructor =
PublicMockStructure.class.getConstructor(long.class, long.class);
@SuppressWarnings("unchecked")
StructuredArray<PublicMockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
PublicMockStructure.class,
length).
elementCtorAndArgsProvider(
new CtorAndArgsProvider() {
@Override
public CtorAndArgs getForContext(
ConstructionContext context) throws NoSuchMethodException {
return new CtorAndArgs(constructor, context.getIndex(), context.getIndex() * 2);
}
}
).
build();
assertCorrectVariableInitialisation(new long[] {length}, array);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgsProvider2() throws NoSuchMethodException {
long length = 9L;
final Constructor<MockStructure> constructor = MockStructure.class.getConstructor(long.class, long.class);
constructor.setAccessible(true); // When constructor is passed in, setAccessible is the caller responsibility...
final CtorAndArgs<MockStructure> ctorAndArgs = new CtorAndArgs<MockStructure>(constructor, (Object[]) null);
final Object[] args = new Object[2];
@SuppressWarnings("unchecked")
StructuredArray<MockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
MockStructure.class,
length).
elementCtorAndArgsProvider(
new CtorAndArgsProvider() {
@Override
public CtorAndArgs getForContext(
ConstructionContext context) throws NoSuchMethodException {
args[0] = context.getIndex();
args[1] = context.getIndex() * 2;
return ctorAndArgs.setArgs(args);
}
}
).
build();
assertCorrectVariableInitialisation(new long[] {length}, array);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgsProvider2Public() throws NoSuchMethodException {
long length = 9L;
final Constructor<PublicMockStructure> constructor =
PublicMockStructure.class.getConstructor(long.class, long.class);
final CtorAndArgs<PublicMockStructure> ctorAndArgs =
new CtorAndArgs<PublicMockStructure>(constructor, (Object[]) null);
final Object[] args = new Object[2];
@SuppressWarnings("unchecked")
StructuredArray<PublicMockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
PublicMockStructure.class,
length).
elementCtorAndArgsProvider(
new CtorAndArgsProvider() {
@Override
public CtorAndArgs getForContext(
ConstructionContext context) throws NoSuchMethodException {
args[0] = context.getIndex();
args[1] = context.getIndex() * 2;
return ctorAndArgs.setArgs(args);
}
}
).
build();
assertCorrectVariableInitialisation(new long[] {length}, array);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgsProvider3() throws NoSuchMethodException {
long length = 9L;
final Constructor<MockStructure> constructor = MockStructure.class.getConstructor(MockStructure.class);
constructor.setAccessible(true); // When constructor is passed in, setAccessible is the caller responsibility...
final MockStructure paramMock = new MockStructure();
final CtorAndArgs<MockStructure> ctorAndArgs = new CtorAndArgs<MockStructure>(constructor, paramMock);
@SuppressWarnings("unchecked")
StructuredArray<MockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
MockStructure.class,
length).
elementCtorAndArgsProvider(
new CtorAndArgsProvider() {
@Override
public CtorAndArgs getForContext(
ConstructionContext context) throws NoSuchMethodException {
paramMock.setIndex(context.getIndex());
paramMock.setTestValue(context.getIndex() * 2);
return ctorAndArgs;
}
}
).
build();
assertCorrectVariableInitialisation(new long[] {length}, array);
}
@Test
public void shouldConstructArrayOfGivenLengthWithBuilderAndCtorAndArgsProvider3Public() throws NoSuchMethodException {
long length = 9L;
final Constructor<PublicMockStructure> constructor =
PublicMockStructure.class.getConstructor(PublicMockStructure.class);
final PublicMockStructure paramMock = new PublicMockStructure();
final CtorAndArgs<PublicMockStructure> ctorAndArgs =
new CtorAndArgs<PublicMockStructure>(constructor, paramMock);
@SuppressWarnings("unchecked")
StructuredArray<PublicMockStructure> array =
new StructuredArrayBuilder(
StructuredArray.class,
PublicMockStructure.class,
length).
elementCtorAndArgsProvider(
new CtorAndArgsProvider() {
@Override
public CtorAndArgs getForContext(
ConstructionContext context) throws NoSuchMethodException {
paramMock.setIndex(context.getIndex());
paramMock.setTestValue(context.getIndex() * 2);
return ctorAndArgs;
}
}
).
build();
assertCorrectVariableInitialisation(new long[] {length}, array);
}
@Test
public void shouldConstructArrayFromCollection() throws NoSuchMethodException {
long length = 100;
ArrayList<MockStructure> mockSource = new ArrayList<MockStructure>();
for (int i = 0; i < length; i++) {
mockSource.add(new MockStructure(i, i*2));
}
@SuppressWarnings("unchecked")
StructuredArray<MockStructure> mocks =
StructuredArray.newInstance(lookup, StructuredArray.class, MockStructure.class, mockSource);
assertThat(valueOf(mocks.get(5).getIndex()), is(valueOf(5)));
assertCorrectVariableInitialisation(new long[] {length}, mocks);
}
@Test
public void shouldConstructArrayFromCollectionPublic() throws NoSuchMethodException {
long length = 100;
ArrayList<PublicMockStructure> mockSource = new ArrayList<PublicMockStructure>();
for (int i = 0; i < length; i++) {
mockSource.add(new PublicMockStructure(i, i*2));
}
@SuppressWarnings("unchecked")
StructuredArray<PublicMockStructure> mocks = StructuredArray.newInstance(StructuredArray.class,
PublicMockStructure.class, mockSource);
assertThat(valueOf(mocks.get(5).getIndex()), is(valueOf(5)));
assertCorrectVariableInitialisation(new long[] {length}, mocks);
}
@Test
public void shouldConstructArrayElementsViaConstantCtorAndArgsProvider() throws NoSuchMethodException {
final Class[] initArgTypes = {long.class, long.class};
final long expectedIndex = 4L;
final long expectedValue = 777L;
long length = 9L;
final CtorAndArgs<MockStructure> ctorAndArgs =
new CtorAndArgs<MockStructure>(lookup, MockStructure.class, initArgTypes, expectedIndex, expectedValue);
final CtorAndArgsProvider<MockStructure> ctorAndArgsProvider =
new CtorAndArgsProvider<MockStructure>() {
@Override
public CtorAndArgs<MockStructure> getForContext(
ConstructionContext<MockStructure> context) throws NoSuchMethodException {
return ctorAndArgs;
}
};
final StructuredArray<MockStructure> array =
StructuredArray.newInstance(MockStructure.class, ctorAndArgsProvider, length);
assertCorrectFixedInitialisation(expectedIndex, expectedValue, new long[]{length}, array);
}
@Test
public void shouldConstructArrayElementsViaConstantCtorAndArgsProviderPublic() throws NoSuchMethodException {
final Class[] initArgTypes = {long.class, long.class};
final long expectedIndex = 4L;
final long expectedValue = 777L;
long length = 9L;
final CtorAndArgs<PublicMockStructure> ctorAndArgs =
new CtorAndArgs<PublicMockStructure>(PublicMockStructure.class, initArgTypes, expectedIndex, expectedValue);
final CtorAndArgsProvider<PublicMockStructure> ctorAndArgsProvider =
new CtorAndArgsProvider<PublicMockStructure>() {
@Override
public CtorAndArgs<PublicMockStructure> getForContext(
ConstructionContext<PublicMockStructure> context) throws NoSuchMethodException {
return ctorAndArgs;
}
};
final StructuredArray<PublicMockStructure> array =
StructuredArray.newInstance(PublicMockStructure.class, ctorAndArgsProvider, length);
assertCorrectFixedInitialisation(expectedIndex, expectedValue, new long[] {length}, array);
}
@Test
public void shouldConstructArrayElementsViaCtorAndArgsProvider() throws NoSuchMethodException {
final long[] lengths = {9};
final DefaultMockCtorAndArgsProvider ctorAndArgsProvider = new DefaultMockCtorAndArgsProvider();
final StructuredArray<MockStructure> array =
StructuredArray.newInstance(MockStructure.class, ctorAndArgsProvider, lengths[0]);
assertCorrectVariableInitialisation(lengths, array);
}
@Test
public void shouldConstructArrayElementsViaCtorAndArgsProviderPublic() throws NoSuchMethodException {
final long[] lengths = {9};
final DefaultPublicMockCtorAndArgsProvider ctorAndArgsProvider =
new DefaultPublicMockCtorAndArgsProvider();
final StructuredArray<PublicMockStructure> array =
StructuredArray.newInstance(PublicMockStructure.class, ctorAndArgsProvider, lengths[0]);
assertCorrectVariableInitialisation(lengths, array);
}
@SuppressWarnings("unchecked")
@Test
public void shouldConstructArrayElementsViaCtorAndArgsProvider3D() throws NoSuchMethodException {
final long[] lengths = {7, 8, 9};
final DefaultMockCtorAndArgsProvider ctorAndArgsProvider = new DefaultMockCtorAndArgsProvider();
final StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<MockStructure>>>,
StructuredArray<StructuredArray<MockStructure>>> builder = get3dBuilder(lengths);
builder.getStructuredSubArrayBuilder().
getStructuredSubArrayBuilder().
elementCtorAndArgsProvider(ctorAndArgsProvider);
final StructuredArray<StructuredArray<StructuredArray<MockStructure>>> array = builder.build();
assertCorrectVariableInitialisation(lengths, array);
}
@SuppressWarnings("unchecked")
@Test
public void shouldConstructArrayElementsViaCtorAndArgsProvider3DPublic() throws NoSuchMethodException {
final long[] lengths = {7, 8, 9};
final DefaultPublicMockCtorAndArgsProvider ctorAndArgsProvider =
new DefaultPublicMockCtorAndArgsProvider();
final StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<PublicMockStructure>>>,
StructuredArray<StructuredArray<PublicMockStructure>>> builder = get3dBuilderPublic(lengths);
builder.getStructuredSubArrayBuilder().
getStructuredSubArrayBuilder().
elementCtorAndArgsProvider(ctorAndArgsProvider);
final StructuredArray<StructuredArray<StructuredArray<PublicMockStructure>>> array = builder.build();
assertCorrectVariableInitialisation(lengths, array);
}
@Test
public void shouldConstructArrayElementsViaLambdas() throws NoSuchMethodException {
// Uncomment for Java 8, keep commented for Java 7 and 6
//
// final Constructor<MockStructure> constructor =
// MockStructure.class.getConstructor(Long.TYPE, Long.TYPE);
//
// final long length = 8;
// final StructuredArray<MockStructure> array =
// StructuredArray.newInstance(MockStructure.class,
// context -> new CtorAndArgs<MockStructure>(
// constructor,
// context.getIndex(), context.getIndex() * 2),
// length);
//
// assertCorrectVariableInitialisation(new long[] {length}, array);
//
// final long[] lengths = {7, 8, 9};
//
// final StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<MockStructure>>>,
// StructuredArray<StructuredArray<MockStructure>>> builder = get3dBuilder(lengths);
// builder.getSubArrayBuilder().getSubArrayBuilder().elementCtorAndArgsProvider(
// context -> {
// long indexSum = 0;
// for (ConstructionContext c = context; c != null; c = c.getContainingContext()) {
// indexSum += c.getIndex();
// }
// return new CtorAndArgs<MockStructure>(constructor,
// indexSum, (indexSum * 2L));
// }
// );
//
// final StructuredArray<StructuredArray<StructuredArray<MockStructure>>> array2 = builder.build();
//
// assertCorrectVariableInitialisation(lengths, array2);
}
@Test
public void shouldSetAndGetCorrectValueAtGivenIndex() throws NoSuchMethodException {
final long[] lengths = {11, 10, 3};
final StructuredArray<StructuredArray<StructuredArray<MockStructure>>> array = get3dBuilder(lengths).build();
initValues(lengths, array);
assertCorrectVariableInitialisation(lengths, array);
}
@Test
public void shouldIterateOverArray() throws NoSuchMethodException {
final long[] lengths = {11};
final StructuredArray<MockStructure> array =
StructuredArray.newInstance(lookup, MockStructure.class, lengths[0]);
initValues(lengths, array);
StructuredArray<MockStructure>.ElementIterator iter = array.iterator();
long sum = 0;
long elementCount = 0;
while (iter.hasNext()) {
final long index = iter.getCursor();
final MockStructure mockStructure = iter.next();
assertThat(valueOf(mockStructure.getIndex()), is(valueOf(index)));
assertThat(valueOf(mockStructure.getTestValue()), is(valueOf(index * 2)));
sum += index;
elementCount++;
}
long sum2 = 0;
long elementCount2 = 0;
for (final MockStructure mockStructure : array) {
sum2 += mockStructure.getIndex();
elementCount2++;
}
assertThat(valueOf(elementCount), is(valueOf(array.getLength())));
assertThat(valueOf(sum), is(valueOf(sum2)));
assertThat(valueOf(elementCount), is(valueOf(elementCount2)));
}
@Test
public void shouldIterateOverArrayAndResetAgain() throws NoSuchMethodException {
final long length = 11;
final StructuredArray<MockStructure> array =
StructuredArray.newInstance(lookup, MockStructure.class, length);
initValues(new long[] {length}, array);
int i = 0;
final StructuredArray<MockStructure>.ElementIterator iter = array.iterator();
while (iter.hasNext()) {
final long index = iter.getCursor();
final MockStructure mockStructure = iter.next();
assertThat(valueOf(mockStructure.getIndex()), is(valueOf(index)));
assertThat(valueOf(mockStructure.getTestValue()), is(valueOf(index * 2)));
i++;
}
iter.reset();
i = 0;
while (iter.hasNext()) {
final long index = iter.getCursor();
final MockStructure mockStructure = iter.next();
assertThat(valueOf(mockStructure.getIndex()), is(valueOf(index)));
assertThat(valueOf(mockStructure.getTestValue()), is(valueOf(index * 2)));
i++;
}
assertThat(valueOf(i), is(valueOf(length)));
}
@Test
public void shouldConstructCopyOfArray() throws NoSuchMethodException {
final long length = 15;
final DefaultMockCtorAndArgsProvider ctorAndArgsProvider = new DefaultMockCtorAndArgsProvider();
final StructuredArray<MockStructure> sourceArray =
StructuredArray.newInstance(MockStructure.class, ctorAndArgsProvider, length);
assertThat(valueOf(sourceArray.getLength()), is(valueOf(length)));
assertTrue(sourceArray.getElementClass() == MockStructure.class);
final StructuredArray<MockStructure> newArray = StructuredArray.copyInstance(lookup, sourceArray);
// We expect MockStructure elements to be initialized with index = index, and testValue = index * 2:
assertCorrectVariableInitialisation(new long[]{length}, newArray);
}
@Test
public void shouldConstructCopyOfArrayPublic() throws NoSuchMethodException {
final long length = 15;
final DefaultPublicMockCtorAndArgsProvider ctorAndArgsProvider = new DefaultPublicMockCtorAndArgsProvider();
final StructuredArray<PublicMockStructure> sourceArray =
StructuredArray.newInstance(PublicMockStructure.class, ctorAndArgsProvider, length);
assertThat(valueOf(sourceArray.getLength()), is(valueOf(length)));
assertTrue(sourceArray.getElementClass() == PublicMockStructure.class);
final StructuredArray<PublicMockStructure> newArray = StructuredArray.copyInstance(sourceArray);
// We expect PublicMockStructure elements to be initialized with index = index, and testValue = index * 2:
assertCorrectVariableInitialisation(new long[] {length}, newArray);
}
@SuppressWarnings("unchecked")
@Test
public void shouldConstructCopyOfArray3D() throws NoSuchMethodException {
final long[] lengths = {15, 7, 5};
final DefaultMockCtorAndArgsProvider ctorAndArgsProvider = new DefaultMockCtorAndArgsProvider();
final StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<MockStructure>>>,
StructuredArray<StructuredArray<MockStructure>>> builder = get3dBuilder(lengths);
builder.getStructuredSubArrayBuilder().
getStructuredSubArrayBuilder().
elementCtorAndArgsProvider(ctorAndArgsProvider);
final StructuredArray<StructuredArray<StructuredArray<MockStructure>>> sourceArray = builder.build();
StructuredArray<StructuredArray<MockStructure>> subArray1 = sourceArray.get(0);
StructuredArray<MockStructure> subArray2 = subArray1.get(0);
assertThat(valueOf(sourceArray.getLength()), is(valueOf(lengths[0])));
assertThat(valueOf(subArray1.getLength()), is(valueOf(lengths[1])));
assertThat(valueOf(subArray2.getLength()), is(valueOf(lengths[2])));
assertTrue(subArray2.getElementClass() == MockStructure.class);
final StructuredArray<StructuredArray<StructuredArray<MockStructure>>> newArray =
StructuredArray.copyInstance(lookup, sourceArray);
// We expect MockStructure elements to be initialized with index = index, and testValue = index * 2:
assertCorrectVariableInitialisation(lengths, newArray);
}
@SuppressWarnings("unchecked")
@Test
public void shouldConstructCopyOfArray3DPublic() throws NoSuchMethodException {
final long[] lengths = {15, 7, 5};
final DefaultPublicMockCtorAndArgsProvider ctorAndArgsProvider = new DefaultPublicMockCtorAndArgsProvider();
final StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<PublicMockStructure>>>,
StructuredArray<StructuredArray<PublicMockStructure>>> builder = get3dBuilderPublic(lengths);
builder.getStructuredSubArrayBuilder().
getStructuredSubArrayBuilder().
elementCtorAndArgsProvider(ctorAndArgsProvider);
final StructuredArray<StructuredArray<StructuredArray<PublicMockStructure>>> sourceArray = builder.build();
StructuredArray<StructuredArray<PublicMockStructure>> subArray1 = sourceArray.get(0);
StructuredArray<PublicMockStructure> subArray2 = subArray1.get(0);
assertThat(valueOf(sourceArray.getLength()), is(valueOf(lengths[0])));
assertThat(valueOf(subArray1.getLength()), is(valueOf(lengths[1])));
assertThat(valueOf(subArray2.getLength()), is(valueOf(lengths[2])));
assertTrue(subArray2.getElementClass() == PublicMockStructure.class);
final StructuredArray<StructuredArray<StructuredArray<PublicMockStructure>>> newArray =
StructuredArray.copyInstance(sourceArray);
// We expect PublicMockStructure elements to be initialized with index = index, and testValue = index * 2:
assertCorrectVariableInitialisation(lengths, newArray);
}
@SuppressWarnings("unchecked")
@Test
public void shouldConstructCopyOfArrayRange() throws NoSuchMethodException {
final long[] lengths = {15, 7, 5};
final DefaultMockCtorAndArgsProvider ctorAndArgsProvider = new DefaultMockCtorAndArgsProvider();
final StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<MockStructure>>>,
StructuredArray<StructuredArray<MockStructure>>> builder = get3dBuilder(lengths);
builder.getStructuredSubArrayBuilder().
getStructuredSubArrayBuilder().
elementCtorAndArgsProvider(ctorAndArgsProvider);
final StructuredArray<StructuredArray<StructuredArray<MockStructure>>> sourceArray = builder.build();
StructuredArray<StructuredArray<MockStructure>> subArray1 = sourceArray.get(0);
StructuredArray<MockStructure> subArray2 = subArray1.get(0);
assertThat(valueOf(sourceArray.getLength()), is(valueOf(lengths[0])));
assertThat(valueOf(subArray1.getLength()), is(valueOf(lengths[1])));
assertThat(valueOf(subArray2.getLength()), is(valueOf(lengths[2])));
assertTrue(subArray2.getElementClass() == MockStructure.class);
long[] offsets = {2, 2, 2};
long[] counts = {13, 5, 3};
final StructuredArray<StructuredArray<StructuredArray<MockStructure>>> newArray =
StructuredArray.copyInstance(lookup, sourceArray, offsets, counts);
assertCorrectVariableInitialisation(counts, newArray, 2);
}
@Test(expected = ArrayIndexOutOfBoundsException.class)
public void shouldThrowOutOfBoundExceptionForAccessesOutOfBounds() throws NoSuchMethodException {
final long length = 11;
final StructuredArray<MockStructure> array =
StructuredArray.newInstance(lookup, MockStructure.class, length);
array.get(length);
}
@Test
public void shouldNotThrowIncompatibleTypeExceptionForGetsOfProperTypes() throws NoSuchMethodException {
final long[] lengths = {11, 7, 4};
final StructuredArray<StructuredArray<StructuredArray<MockStructure>>> array = get3dBuilder(lengths).build();
// Step by step gets of the correct type (array vs. element) per dimension:
StructuredArray<StructuredArray<MockStructure>> subArray1 = array.get(2);
StructuredArray<MockStructure> subArray2 = subArray1.get(2);
subArray2.get(2);
}
@Test
public void shouldCopyRegionLeftInArray() throws NoSuchMethodException {
final long length = 11;
final StructuredArray<MockStructure> array =
StructuredArray.newInstance(lookup, MockStructure.class, length);
initValues(new long[]{length}, array);
StructuredArray.shallowCopy(array, 4, array, 3, 2, false);
assertThat(valueOf(array.get(3).getIndex()), is(valueOf(4)));
assertThat(valueOf(array.get(4).getIndex()), is(valueOf(5)));
assertThat(valueOf(array.get(5).getIndex()), is(valueOf(5)));
}
@Test
public void shouldCopyRegionRightInArray() throws NoSuchMethodException {
final long length = 11;
final StructuredArray<MockStructure> array =
StructuredArray.newInstance(lookup, MockStructure.class, length);
initValues(new long[]{length}, array);
StructuredArray.shallowCopy(array, 5, array, 6, 2, false);
assertThat(valueOf(array.get(5).getIndex()), is(valueOf(5)));
assertThat(valueOf(array.get(6).getIndex()), is(valueOf(5)));
assertThat(valueOf(array.get(7).getIndex()), is(valueOf(6)));
}
@Test
public void shouldCopyEvenWithFinalFields() throws NoSuchMethodException {
final long length = 11;
final StructuredArray<MockStructureWithFinalField> array =
StructuredArray.newInstance(lookup, MockStructureWithFinalField.class, length);
StructuredArray.shallowCopy(array, 1, array, 3, 1, true);
}
@Test(expected = IllegalArgumentException.class)
public void shouldThrowExceptionWhenFinalFieldWouldBeCopied() throws NoSuchMethodException {
final long length = 11;
final StructuredArray<MockStructureWithFinalField> array =
StructuredArray.newInstance(lookup, MockStructureWithFinalField.class, length);
StructuredArray.shallowCopy(array, 1, array, 3, 1);
}
@Test
public void moveObjectsIntoNewArray() throws NoSuchMethodException {
int length = 100;
ArrayList<MockStructure> sourceMocks = new ArrayList<MockStructure>(length);
for (int i = 0; i < length; i++) {
sourceMocks.add(new MockStructure(i, i * 2));
}
@SuppressWarnings("unchecked")
StructuredArrayBuilder<StructuredArray<MockStructure>, MockStructure> builder =
new StructuredArrayBuilder(
lookup,
StructuredArray.class,
MockStructure.class,
length
);
builder.elementCtorAndArgsProvider(new CopyFromArrayListProvider(sourceMocks));
StructuredArray<MockStructure> mocks = builder.build();
assertThat(valueOf(mocks.get(5).getIndex()), is(valueOf(5)));
assertThat(valueOf(mocks.get(5).getTestValue()), is(valueOf(10)));
MockStructure mock = mocks.get(7);
}
///////////////////////////////////////////////////////////////////////////////////////////////
// Test support below
///////////////////////////////////////////////////////////////////////////////////////////////
private <T extends MockStructure> void assertCorrectFixedInitialisation(
final long expectedIndex,
final long expectedValue,
final long[] lengths,
final StructuredArray<T> array) {
StructuredArray a = array;
for (int i = 0; i < lengths.length - 1; i++) {
assertThat(valueOf(a.getLength()), is(valueOf(lengths[i])));
a = (StructuredArray) a.get(0);
}
assertThat(valueOf(a.getLength()), is(valueOf(lengths[lengths.length - 1])));
assertTrue(MockStructure.class.isAssignableFrom(a.getElementClass()));
long totalElementCount = 1;
for (long l : lengths) {
totalElementCount *= l;
}
final long[] cursors = new long[lengths.length];
long elementCountToCursor = 0;
while (elementCountToCursor < totalElementCount) {
// Check element at cursors:
// Check element at cursors:
a = array;
for (int i = 0; i < cursors.length - 1; i++) {
a = (StructuredArray) a.get(cursors[i]);
}
MockStructure mockStructure = (MockStructure) a.get(cursors[cursors.length - 1]);
assertThat(valueOf(mockStructure.getIndex()), is(valueOf(expectedIndex)));
assertThat(valueOf(mockStructure.getTestValue()), is(valueOf(expectedValue)));
// Increment cursors from inner-most dimension out:
for (int cursorDimension = cursors.length - 1; cursorDimension >= 0; cursorDimension--) {
if ((++cursors[cursorDimension]) < lengths[cursorDimension]) {
break;
}
// This dimension wrapped. Reset to zero and continue to one dimension higher
cursors[cursorDimension] = 0;
}
elementCountToCursor++;
}
}
private void assertCorrectVariableInitialisation(final long[] lengths,
final StructuredArray array) {
assertCorrectVariableInitialisation(lengths, array, 0);
}
private void assertCorrectVariableInitialisation(final long[] lengths,
final StructuredArray array, long indexOffset) {
StructuredArray a = array;
for (int i = 0; i < lengths.length - 1; i++) {
assertThat(valueOf(a.getLength()), is(valueOf(lengths[i])));
a = (StructuredArray) a.get(0);
}
assertThat(valueOf(a.getLength()), is(valueOf(lengths[lengths.length - 1])));
assertTrue(MockStructure.class.isAssignableFrom(a.getElementClass()));
long totalElementCount = 1;
for (long l : lengths) {
totalElementCount *= l;
}
final long[] cursors = new long[lengths.length];
long elementCountToCursor = 0;
while (elementCountToCursor < totalElementCount) {
// Check element at cursors:
a = array;
for (int i = 0; i < cursors.length - 1; i++) {
a = (StructuredArray) a.get(cursors[i]);
}
MockStructure mockStructure = (MockStructure) a.get(cursors[cursors.length - 1]);
long indexSum = 0;
String cursorsString = "";
for (long index : cursors) {
indexSum += index + indexOffset;
cursorsString += index + ",";
}
assertThat("elementCountToCursor: " + elementCountToCursor + " cursors: " + cursorsString,
valueOf(mockStructure.getIndex()), is(valueOf(indexSum)));
assertThat("elementCountToCursor: " + elementCountToCursor + " cursors: " + cursorsString,
valueOf(mockStructure.getTestValue()), is(valueOf(indexSum * 2)));
// Increment cursors from inner-most dimension out:
for (int cursorDimension = cursors.length - 1; cursorDimension >= 0; cursorDimension--) {
if ((++cursors[cursorDimension]) < lengths[cursorDimension]) {
break;
}
// This dimension wrapped. Reset to zero and continue to one dimension higher
cursors[cursorDimension] = 0;
}
elementCountToCursor++;
}
}
private void initValues(final long[] lengths, final StructuredArray array) {
final long[] cursors = new long[lengths.length];
long totalElementCount = 1;
for (long l : lengths) {
totalElementCount *= l;
}
long elementCountToCursor = 0;
while (elementCountToCursor < totalElementCount) {
// Check element at cursors:
StructuredArray a = array;
for (int i = 0; i < cursors.length - 1; i++) {
a = (StructuredArray) a.get(cursors[i]);
}
MockStructure mockStructure = (MockStructure) a.get(cursors[cursors.length - 1]);
long indexSum = 0;
for (long index : cursors) {
indexSum += index;
}
mockStructure.setIndex(indexSum);
mockStructure.setTestValue(indexSum * 2);
// Increment cursors from inner-most dimension out:
for (int cursorDimension = cursors.length - 1; cursorDimension >= 0; cursorDimension--) {
if ((++cursors[cursorDimension]) < lengths[cursorDimension]) {
break;
}
// This dimension wrapped. Reset to zero and continue to one dimension higher
cursors[cursorDimension] = 0;
}
elementCountToCursor++;
}
}
public static class PublicMockStructure extends MockStructure {
public PublicMockStructure() {
}
public PublicMockStructure(final long index, final long testValue) {
super(index, testValue);
}
public PublicMockStructure(final PublicMockStructure src) {
super(src);
}
}
private static class MockStructure {
private long index = -1;
private long testValue = Long.MIN_VALUE;
public MockStructure() {
}
public MockStructure(final long index, final long testValue) {
this.index = index;
this.testValue = testValue;
}
public MockStructure(final MockStructure src) {
this.index = src.index;
this.testValue = src.testValue;
}
public long getIndex() {
return index;
}
public void setIndex(final long index) {
this.index = index;
}
public long getTestValue() {
return testValue;
}
public void setTestValue(final long testValue) {
this.testValue = testValue;
}
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final MockStructure that = (MockStructure)o;
return index == that.index && testValue == that.testValue;
}
public int hashCode() {
int result = (int)(index ^ (index >>> 32));
result = 31 * result + (int)(testValue ^ (testValue >>> 32));
return result;
}
public String toString() {
return "MockStructure{" +
"index=" + index +
", testValue=" + testValue +
'}';
}
}
public static class MockStructureWithFinalField {
private final int value = 888;
}
private static class DefaultPublicMockCtorAndArgsProvider implements CtorAndArgsProvider<PublicMockStructure> {
private final Class[] argsTypes = {Long.TYPE, Long.TYPE};
public CtorAndArgs<PublicMockStructure> getForContext(
ConstructionContext<PublicMockStructure> context) throws NoSuchMethodException {
long indexSum = 0;
for (ConstructionContext c = context; c != null; c = c.getContainingContext()) {
indexSum += c.getIndex();
}
Object[] args = {indexSum, indexSum * 2};
// We could do this much more efficiently with atomic caching of a single allocated CtorAndArgs,
// as CopyCtorAndArgsProvider does, but no need to put in the effort in a test...
return new CtorAndArgs<PublicMockStructure>(PublicMockStructure.class, argsTypes, args);
}
}
private static class DefaultMockCtorAndArgsProvider implements CtorAndArgsProvider<MockStructure> {
private final Class[] argsTypes = {Long.TYPE, Long.TYPE};
public CtorAndArgs<MockStructure> getForContext(ConstructionContext<MockStructure> context) throws NoSuchMethodException {
long indexSum = 0;
for (ConstructionContext c = context; c != null; c = c.getContainingContext()) {
indexSum += c.getIndex();
}
Object[] args = {indexSum, indexSum * 2};
// We could do this much more efficiently with atomic caching of a single allocated CtorAndArgs,
// as CopyCtorAndArgsProvider does, but no need to put in the effort in a test...
return new CtorAndArgs<MockStructure>(lookup, MockStructure.class, argsTypes, args);
}
}
private static class CopyFromArrayListProvider implements CtorAndArgsProvider<MockStructure> {
static final Constructor<MockStructure> copyCtor;
static {
try {
copyCtor = MockStructure.class.getConstructor(new Class[]{MockStructure.class});
copyCtor.setAccessible(true); // When constructor is passed in, setAccessible is the caller responsibility...
} catch (NoSuchMethodException ex) {
throw new RuntimeException(ex);
}
}
private final ArrayList<MockStructure> fromList;
public CopyFromArrayListProvider(ArrayList<MockStructure> fromList) {
this.fromList = fromList;
}
public CtorAndArgs<MockStructure> getForContext(ConstructionContext<MockStructure> context) throws NoSuchMethodException {
return new CtorAndArgs<MockStructure>(copyCtor, fromList.get((int) context.getIndex()));
}
}
StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<MockStructure>>>,
StructuredArray<StructuredArray<MockStructure>>> get3dBuilder(long... lengths) {
@SuppressWarnings("unchecked")
StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<MockStructure>>>,
StructuredArray<StructuredArray<MockStructure>>> builder =
new StructuredArrayBuilder(
StructuredArray.class,
new StructuredArrayBuilder(
StructuredArray.class,
new StructuredArrayBuilder(
lookup,
StructuredArray.class,
MockStructure.class,
lengths[2]
),
lengths[1]
),
lengths[0]
);
return builder;
}
StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<PublicMockStructure>>>,
StructuredArray<StructuredArray<PublicMockStructure>>> get3dBuilderPublic(long... lengths) {
@SuppressWarnings("unchecked")
StructuredArrayBuilder<StructuredArray<StructuredArray<StructuredArray<PublicMockStructure>>>,
StructuredArray<StructuredArray<PublicMockStructure>>> builder =
new StructuredArrayBuilder(
StructuredArray.class,
new StructuredArrayBuilder(
StructuredArray.class,
new StructuredArrayBuilder(
StructuredArray.class,
PublicMockStructure.class,
lengths[2]
),
lengths[1]
),
lengths[0]
);
return builder;
}
}