From b044b17b7c455d6f23b0a4f8da7550d997036caa Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sat, 14 Oct 2006 16:47:22 +0000 Subject: Moved tests to separate project. --- .../amazon/carbonado/raw/TestEncodingStrategy.java | 857 --------------------- 1 file changed, 857 deletions(-) delete mode 100644 src/test/java/com/amazon/carbonado/raw/TestEncodingStrategy.java (limited to 'src/test/java/com/amazon/carbonado/raw/TestEncodingStrategy.java') diff --git a/src/test/java/com/amazon/carbonado/raw/TestEncodingStrategy.java b/src/test/java/com/amazon/carbonado/raw/TestEncodingStrategy.java deleted file mode 100644 index 11a4eca..0000000 --- a/src/test/java/com/amazon/carbonado/raw/TestEncodingStrategy.java +++ /dev/null @@ -1,857 +0,0 @@ -/* - * Copyright 2006 Amazon Technologies, Inc. or its affiliates. - * Amazon, Amazon.com and Carbonado are trademarks or registered trademarks - * of Amazon Technologies, Inc. or its affiliates. All rights reserved. - * - * 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.amazon.carbonado.raw; - -import java.lang.reflect.*; -import java.util.*; - -import junit.framework.TestCase; -import junit.framework.TestSuite; - -import org.cojen.classfile.*; -import org.cojen.util.*; - -import com.amazon.carbonado.*; -import com.amazon.carbonado.info.*; -import com.amazon.carbonado.spi.*; - -/** - * Test case for {@link GenericEncodingStrategy}. - *

- * It generates random selections of properties, encodes with random values, - * and checks that the decoding produces the original results. In addition, the - * proper ordering of encoded keys is checked. - * - * @author Brian S O'Neill - */ -public class TestEncodingStrategy extends TestCase { - private static final int SHORT_TEST = 100; - private static final int MEDIUM_TEST = 500; - private static final int LONG_TEST = 1000; - - private static final int ENCODE_OBJECT_ARRAY = 0; - private static final int DECODE_OBJECT_ARRAY = 1; - private static final int ENCODE_OBJECT_ARRAY_PARTIAL = 2; - - private static final int BOGUS_GENERATION = 99; - - // Make sure BOGUS_GENERATION is not included. - private static final int[] GENERATIONS = {-1, 0, 1, 2, 127, 128, 129, Integer.MAX_VALUE}; - - public static void main(String[] args) { - junit.textui.TestRunner.run(suite()); - } - - public static TestSuite suite() { - return new TestSuite(TestEncodingStrategy.class); - } - - private final long mSeed; - private final StorableProperty[] mProperties; - - private Random mRandom; - - public TestEncodingStrategy(String name) { - super(name); - mSeed = 986184829029842L; - Collection> properties = - StorableIntrospector.examine(TestStorable.class).getAllProperties().values(); - mProperties = properties.toArray(new StorableProperty[0]); - } - - protected void setUp() { - mRandom = new Random(mSeed); - } - - protected void tearDown() { - } - - public void test_dataEncoding_noProperties() throws Exception { - for (int generation : GENERATIONS) { - test_dataEncoding_noProperties(0, 0, generation); - } - } - - public void test_dataEncoding_noProperties_prefix() throws Exception { - for (int generation : GENERATIONS) { - test_dataEncoding_noProperties(5, 0, generation); - } - } - - public void test_dataEncoding_noProperties_suffix() throws Exception { - for (int generation : GENERATIONS) { - test_dataEncoding_noProperties(0, 7, generation); - } - } - - public void test_dataEncoding_noProperties_prefixAndSuffix() throws Exception { - for (int generation : GENERATIONS) { - test_dataEncoding_noProperties(5, 7, generation); - } - } - - private void test_dataEncoding_noProperties(int prefix, int suffix, int generation) - throws Exception - { - GenericEncodingStrategy strategy = new GenericEncodingStrategy - (TestStorable.class, null, 0, 0, prefix, suffix); - - Method[] methods = generateCodecMethods - (strategy, new StorableProperty[0], null, generation); - - byte[] encoded = (byte[]) methods[ENCODE_OBJECT_ARRAY] - .invoke(null, new Object[] {new Object[0]}); - - int generationPrefix; - if (generation < 0) { - generationPrefix = 0; - } else if (generation < 128) { - generationPrefix = 1; - } else { - generationPrefix = 4; - } - - assertEquals(encoded.length, prefix + generationPrefix + suffix); - - if (generation >= 0) { - if (generationPrefix == 1) { - assertEquals(generation, encoded[prefix]); - } else { - int actualGeneration = DataDecoder.decodeInt(encoded, prefix); - assertEquals(generation, actualGeneration); - } - } - - // Decode should not throw an exception. - methods[DECODE_OBJECT_ARRAY].invoke(null, new Object[0], encoded); - - // Generation mismatch should throw an exception. - if (generation >= 0) { - encoded[prefix] = BOGUS_GENERATION; - try { - methods[DECODE_OBJECT_ARRAY].invoke(null, new Object[0], encoded); - fail(); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof CorruptEncodingException) { - CorruptEncodingException cee = (CorruptEncodingException) cause; - // Make sure error message includes actual generation. - assertTrue(cee.getMessage().indexOf(String.valueOf(BOGUS_GENERATION)) >= 0); - } else { - throw e; - } - } - } - } - - public void test_dataEncoding_multipleProperties() throws Exception { - for (int generation : GENERATIONS) { - test_dataEncoding_multipleProperties(0, 0, generation); - } - } - - public void test_dataEncoding_multipleProperties_prefix() throws Exception { - for (int generation : GENERATIONS) { - test_dataEncoding_multipleProperties(5, 0, generation); - } - } - - public void test_dataEncoding_multipleProperties_suffix() throws Exception { - for (int generation : GENERATIONS) { - test_dataEncoding_multipleProperties(0, 7, generation); - } - } - - public void test_dataEncoding_multipleProperties_prefixAndSuffix() throws Exception { - for (int generation : GENERATIONS) { - test_dataEncoding_multipleProperties(5, 7, generation); - } - } - - /** - * @param generation when non-negative, encode a storable layout generation - * value in one or four bytes. - */ - private void test_dataEncoding_multipleProperties(int prefix, int suffix, int generation) - throws Exception - { - GenericEncodingStrategy strategy = new GenericEncodingStrategy - (TestStorable.class, null, 0, 0, prefix, suffix); - - for (int i=0; i[] properties = selectProperties(1, 50); - - Method[] methods = generateCodecMethods(strategy, properties, null, generation); - Object[] values = selectPropertyValues(properties); - - byte[] encoded = (byte[]) methods[ENCODE_OBJECT_ARRAY] - .invoke(null, new Object[] {values}); - - int generationPrefix; - if (generation < 0) { - generationPrefix = 0; - } else if (generation < 128) { - generationPrefix = 1; - } else { - generationPrefix = 4; - } - - assertTrue(encoded.length > (prefix + generationPrefix + suffix)); - - if (generation >= 0) { - if (generationPrefix == 1) { - assertEquals(generation, encoded[prefix]); - } else { - int actualGeneration = DataDecoder.decodeInt(encoded, prefix); - assertEquals(generation, actualGeneration); - } - } - - if (prefix > 0) { - // Fill in with data which should be ignored by decoder. - for (int p=0; p 0) { - // Fill in with data which should be ignored by decoder. - for (int p=0; p= 0) { - encoded[prefix] = BOGUS_GENERATION; - try { - methods[DECODE_OBJECT_ARRAY].invoke(null, new Object[0], encoded); - fail(); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof CorruptEncodingException) { - CorruptEncodingException cee = (CorruptEncodingException) cause; - // Make sure error message includes actual generation. - assertTrue - (cee.getMessage().indexOf(String.valueOf(BOGUS_GENERATION)) >= 0); - } else { - throw e; - } - } - } - } - } - - public void test_keyEncoding_noProperties() throws Exception { - test_keyEncoding_noProperties(0, 0); - } - - public void test_keyEncoding_noProperties_prefix() throws Exception { - test_keyEncoding_noProperties(5, 0); - } - - public void test_keyEncoding_noProperties_suffix() throws Exception { - test_keyEncoding_noProperties(0, 7); - } - - public void test_keyEncoding_noProperties_prefixAndSuffix() throws Exception { - test_keyEncoding_noProperties(5, 7); - } - - private void test_keyEncoding_noProperties(int prefix, int suffix) throws Exception { - GenericEncodingStrategy strategy = new GenericEncodingStrategy - (TestStorable.class, null, prefix, suffix, 0, 0); - - Method[] methods = generateCodecMethods - (strategy, new StorableProperty[0], new Direction[0], -1); - - // Encode should return an empty array. - byte[] encoded = (byte[]) methods[ENCODE_OBJECT_ARRAY] - .invoke(null, new Object[] {new Object[0]}); - assertEquals(encoded.length, prefix + suffix); - - // Decode should not throw an exception. - methods[DECODE_OBJECT_ARRAY].invoke(null, new Object[0], encoded); - } - - public void test_keyEncoding_multipleProperties() throws Exception { - test_keyEncoding_multipleProperties(0, 0); - } - - public void test_keyEncoding_multipleProperties_prefix() throws Exception { - test_keyEncoding_multipleProperties(5, 0); - } - - public void test_keyEncoding_multipleProperties_suffix() throws Exception { - test_keyEncoding_multipleProperties(0, 7); - } - - public void test_keyEncoding_multipleProperties_prefixAndSuffix() throws Exception { - test_keyEncoding_multipleProperties(5, 7); - } - - private void test_keyEncoding_multipleProperties(int prefix, int suffix) throws Exception { - GenericEncodingStrategy strategy = new GenericEncodingStrategy - (TestStorable.class, null, prefix, suffix, 0, 0); - - for (int i=0; i[] properties = selectProperties(1, 50); - Direction[] directions = selectDirections(properties.length); - - Method[] methods = generateCodecMethods(strategy, properties, directions, -1); - Object[] values = selectPropertyValues(properties); - - byte[] encoded = (byte[]) methods[ENCODE_OBJECT_ARRAY] - .invoke(null, new Object[] {values}); - - assertTrue(encoded.length > (prefix + suffix)); - - // Encode using partial encoding method, but do all - // properties. Ensure that the encoding is exactly the same. - byte[] encoded2 = (byte[]) methods[ENCODE_OBJECT_ARRAY_PARTIAL] - .invoke(null, new Object[] {values, 0, properties.length}); - assertTrue(Arrays.equals(encoded, encoded2)); - - if (prefix > 0) { - // Fill in with data which should be ignored by decoder. - for (int p=0; p 0) { - // Fill in with data which should be ignored by decoder. - for (int p=0; p 0) { - for (int p=0; p 0) { - for (int p=0; p 0); - } - - if (properties.length == 1) { - break; - } - } - } - } - - public void test_keyEncoding_ordering() throws Exception { - GenericEncodingStrategy strategy = - new GenericEncodingStrategy(TestStorable.class, null, 0, 0, 0, 0); - - for (int i=0; i[] properties = selectProperties(1, 50); - Direction[] directions = selectDirections(properties.length); - Method[] methods = generateCodecMethods(strategy, properties, directions, -1); - - Object[] values_1 = selectPropertyValues(properties); - byte[] encoded_1 = (byte[]) methods[ENCODE_OBJECT_ARRAY] - .invoke(null, new Object[] {values_1}); - - Object[] values_2 = selectPropertyValues(properties); - byte[] encoded_2 = (byte[]) methods[ENCODE_OBJECT_ARRAY] - .invoke(null, new Object[] {values_2}); - - int byteOrder = TestDataEncoding.byteArrayCompare(encoded_1, encoded_2); - int valueOrder = compareValues(properties, directions, values_1, values_2); - - assertEquals(valueOrder, byteOrder); - } - } - - private int compareValues(StorableProperty[] properties, Direction[] directions, - Object[] values_1, Object[] values_2) { - int length = directions.length; - for (int i=0; i property = properties[i]; - Direction direction = directions[i]; - - Object value_1 = values_1[i]; - Object value_2 = values_2[i]; - - int result; - if (property.getType() == byte[].class) { - result = TestDataEncoding.byteArrayOrNullCompare - ((byte[]) value_1, (byte[]) value_2); - } else { - if (value_1 == null) { - if (value_2 == null) { - result = 0; - } else { - result = 1; - } - } else if (value_2 == null) { - result = -1; - } else { - result = Integer.signum(((Comparable) value_1).compareTo(value_2)); - } - } - - if (result != 0) { - if (direction == Direction.DESCENDING) { - result = -result; - } - return result; - } - } - - return 0; - } - - // Method taken from String class and modified a bit. - private static int indexOf(byte[] source, int sourceOffset, int sourceCount, - byte[] target, int targetOffset, int targetCount, - int fromIndex) { - if (fromIndex >= sourceCount) { - return (targetCount == 0 ? sourceCount : -1); - } - if (fromIndex < 0) { - fromIndex = 0; - } - if (targetCount == 0) { - return fromIndex; - } - - byte first = target[targetOffset]; - int max = sourceOffset + (sourceCount - targetCount); - - for (int i = sourceOffset + fromIndex; i <= max; i++) { - // Look for first byte. - if (source[i] != first) { - while (++i <= max && source[i] != first); - } - - // Found first byte, now look at the rest of v2 - if (i <= max) { - int j = i + 1; - int end = j + targetCount - 1; - for (int k = targetOffset + 1; j < end && source[j] == target[k]; j++, k++); - - if (j == end) { - // Found whole string. - return i - sourceOffset; - } - } - } - return -1; - } - - /** - * First method is the encoder, second is the decoder. Both methods are - * static. Encoder accepts an object array of property values, and it - * returns a byte array. Decoder accepts an object array to receive - * property values, an encoded byte array, and it returns void. - * - *

If generating key encoding and the property count is more than zero, - * then third element in array is a key encoder that supports partial - * encoding. In addition to the object array argument, it also accepts an - * int start and an int end argument. The start of the range is inclusive, - * and the end is exclusive. - * - * @param directions when supplied, build key encoding/decoding. Otherwise, - * build data encoding/decoding. - * @param generation when non-negative, encode a storable layout generation - * value in one or four bytes. - */ - private Method[] generateCodecMethods(GenericEncodingStrategy strategy, - StorableProperty[] properties, - Direction[] directions, - int generation) - throws Exception - { - ClassInjector ci = ClassInjector.create(TestStorable.class.getName(), null); - ClassFile cf = new ClassFile(ci.getClassName()); - cf.markSynthetic(); - cf.setTarget("1.5"); - - cf.addDefaultConstructor(); - - TypeDesc byteArrayType = TypeDesc.forClass(byte[].class); - TypeDesc objectArrayType = TypeDesc.forClass(Object[].class); - - // Build encode method. - MethodInfo mi = cf.addMethod(Modifiers.PUBLIC_STATIC, "encode", byteArrayType, - new TypeDesc[] {objectArrayType}); - CodeBuilder b = new CodeBuilder(mi); - LocalVariable encodedVar; - if (directions != null) { - OrderedProperty[] ordered = - makeOrderedProperties(properties, directions); - encodedVar = - strategy.buildKeyEncoding(b, ordered, b.getParameter(0), null, false, null, null); - } else { - encodedVar = strategy.buildDataEncoding - (b, properties, b.getParameter(0), null, false, generation); - } - b.loadLocal(encodedVar); - b.returnValue(byteArrayType); - - // Build decode method. - mi = cf.addMethod(Modifiers.PUBLIC_STATIC, "decode", null, - new TypeDesc[] {objectArrayType, byteArrayType}); - b = new CodeBuilder(mi); - if (directions != null) { - OrderedProperty[] ordered = - makeOrderedProperties(properties, directions); - strategy.buildKeyDecoding - (b, ordered, b.getParameter(0), null, false, b.getParameter(1)); - } else { - strategy.buildDataDecoding - (b, properties, b.getParameter(0), null, false, - generation, null, b.getParameter(1)); - } - b.returnVoid(); - - if (directions != null && properties.length > 0) { - // Build encode partial key method. - mi = cf.addMethod - (Modifiers.PUBLIC_STATIC, "encodePartial", byteArrayType, - new TypeDesc[] {objectArrayType, TypeDesc.INT, TypeDesc.INT}); - b = new CodeBuilder(mi); - OrderedProperty[] ordered = - makeOrderedProperties(properties, directions); - encodedVar = - strategy.buildKeyEncoding(b, ordered, b.getParameter(0), null, false, - b.getParameter(1), b.getParameter(2)); - b.loadLocal(encodedVar); - b.returnValue(byteArrayType); - } - - Class clazz = ci.defineClass(cf); - - Method encode = clazz.getMethod("encode", Object[].class); - Method decode = clazz.getMethod("decode", Object[].class, byte[].class); - Method encodePartial = null; - if (directions != null && properties.length > 0) { - encodePartial = clazz.getMethod("encodePartial", Object[].class, int.class, int.class); - } - - Method[] methods = new Method[3]; - methods[ENCODE_OBJECT_ARRAY] = encode; - methods[DECODE_OBJECT_ARRAY] = decode; - methods[ENCODE_OBJECT_ARRAY_PARTIAL] = encodePartial; - - return methods; - } - - private StorableProperty[] selectProperties(int minCount, int maxCount) { - int length = (minCount == maxCount) ? minCount - : (mRandom.nextInt(maxCount - minCount + 1) + minCount); - - StorableProperty[] selection = new StorableProperty[length]; - - for (int i=length; --i>=0; ) { - selection[i] = mProperties[mRandom.nextInt(mProperties.length)]; - } - - return selection; - } - - private Direction[] selectDirections(int count) { - Direction[] directions = new Direction[count]; - - for (int i=count; --i>=0; ) { - Direction dir; - switch (mRandom.nextInt(3)) { - default: - dir = Direction.UNSPECIFIED; - break; - case 1: - dir = Direction.ASCENDING; - break; - case 2: - dir = Direction.DESCENDING; - break; - } - directions[i] = dir; - } - - return directions; - } - - private OrderedProperty[] makeOrderedProperties - (StorableProperty[] properties, Direction[] directions) { - - int length = properties.length; - OrderedProperty[] ordered = new OrderedProperty[length]; - for (int i=length; --i>=0; ) { - ordered[i] = OrderedProperty.get(properties[i], directions[i]); - } - - return ordered; - } - - /** - * Returns an array of the same size with randomly selected values filled - * in that match the property type. - */ - private Object[] selectPropertyValues(StorableProperty[] properties) { - int length = properties.length; - Object[] values = new Object[length]; - - for (int i=length; --i>=0; ) { - StorableProperty property = properties[i]; - TypeDesc type = TypeDesc.forClass(property.getType()); - - Object value; - - if (property.isNullable() && mRandom.nextInt(100) == 0) { - value = null; - } else { - TypeDesc prim = type.toPrimitiveType(); - if (prim != null) { - switch (prim.getTypeCode()) { - case TypeDesc.BOOLEAN_CODE: default: - value = mRandom.nextBoolean(); - break; - case TypeDesc.CHAR_CODE: - value = (char) mRandom.nextInt(); - break; - case TypeDesc.FLOAT_CODE: - value = Float.intBitsToFloat(mRandom.nextInt()); - break; - case TypeDesc.DOUBLE_CODE: - value = Double.longBitsToDouble(mRandom.nextLong()); - break; - case TypeDesc.BYTE_CODE: - value = (byte) mRandom.nextInt(); - break; - case TypeDesc.SHORT_CODE: - value = (short) mRandom.nextInt(); - break; - case TypeDesc.INT_CODE: - value = mRandom.nextInt(); - break; - case TypeDesc.LONG_CODE: - value = mRandom.nextLong(); - break; - } - } else if (type == TypeDesc.STRING) { - int len = mRandom.nextInt(100); - StringBuilder sb = new StringBuilder(len); - for (int j=0; j