From 556add974e66ba495e882515a822eb50f10e88ee Mon Sep 17 00:00:00 2001 From: "Brian S. O'Neill" Date: Sat, 14 Oct 2006 17:43:50 +0000 Subject: Added layout tests. --- .../com/amazon/carbonado/layout/TestLayout.java | 827 +++++++++++++++++++++ 1 file changed, 827 insertions(+) create mode 100644 src/test/java/com/amazon/carbonado/layout/TestLayout.java (limited to 'src/test/java/com/amazon/carbonado/layout') diff --git a/src/test/java/com/amazon/carbonado/layout/TestLayout.java b/src/test/java/com/amazon/carbonado/layout/TestLayout.java new file mode 100644 index 0000000..9fb97b1 --- /dev/null +++ b/src/test/java/com/amazon/carbonado/layout/TestLayout.java @@ -0,0 +1,827 @@ +/* + * 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.layout; + +import java.util.List; +import java.util.Map; + +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.joda.time.DateTime; + +import org.cojen.classfile.ClassFile; +import org.cojen.classfile.CodeBuilder; +import org.cojen.classfile.Modifiers; +import org.cojen.classfile.TypeDesc; +import org.cojen.classfile.attribute.Annotation; + +import org.cojen.util.BeanPropertyAccessor; +import org.cojen.util.ClassInjector; + +import com.amazon.carbonado.adapter.YesNoAdapter; +import com.amazon.carbonado.PrimaryKey; +import com.amazon.carbonado.Repository; +import com.amazon.carbonado.Storable; +import com.amazon.carbonado.Storage; + +import com.amazon.carbonado.info.StorableInfo; +import com.amazon.carbonado.info.StorableIntrospector; +import com.amazon.carbonado.info.StorableProperty; +import com.amazon.carbonado.info.StorablePropertyAdapter; + +import com.amazon.carbonado.stored.FileInfo; +import com.amazon.carbonado.stored.StorableDateIndex; +import com.amazon.carbonado.stored.StorableTestBasic; +import com.amazon.carbonado.stored.StorableTestMinimal; + +import com.amazon.carbonado.TestUtilities; + +/** + * + * + * @author Brian S O'Neill + */ +public class TestLayout extends TestCase { + private static final String TEST_STORABLE_NAME = "test.TheTestStorableType"; + private static final String TEST_STORABLE_NAME_2 = "test.TheOtherTestStorableType"; + + public static void main(String[] args) { + junit.textui.TestRunner.run(suite()); + } + + public static TestSuite suite() { + return new TestSuite(TestLayout.class); + } + + private Repository mRepository; + private LayoutFactory mFactory; + + public TestLayout(String name) { + super(name); + } + + protected void setUp() throws Exception { + mRepository = TestUtilities.buildTempRepository(); + mFactory = new LayoutFactory(mRepository); + } + + protected void tearDown() throws Exception { + mRepository.close(); + mRepository = null; + } + + public void testBasic() throws Exception { + // Run test twice: First time, records get inserted. Second time, they are loaded. + for (int i=0; i<2; i++) { + Layout layout = mFactory.layoutFor(StorableTestBasic.class); + + assertEquals(StorableTestBasic.class.getName(), layout.getStorableTypeName()); + assertEquals(-8576805570777985009L, layout.getLayoutID()); + assertEquals(0, layout.getGeneration()); + assertTrue(layout.getCreationDateTime().getMillis() > 0); + assertTrue(layout.getCreationDateTime().getMillis() <= System.currentTimeMillis()); + + List properties = layout.getAllProperties(); + + assertEquals(6, properties.size()); + + LayoutProperty property; + + property = properties.get(0); + assertEquals("id", property.getPropertyName()); + assertEquals("I", property.getPropertyTypeDescriptor()); + assertFalse(property.isNullable()); + assertTrue(property.isPrimaryKeyMember()); + assertEquals(null, property.getAdapterTypeName()); + assertEquals(null, property.getAdapterParams()); + + property = properties.get(1); + assertEquals("date", property.getPropertyName()); + assertEquals("Lorg/joda/time/DateTime;", property.getPropertyTypeDescriptor()); + assertTrue(property.isNullable()); + assertFalse(property.isPrimaryKeyMember()); + assertEquals(null, property.getAdapterTypeName()); + assertEquals(null, property.getAdapterParams()); + + property = properties.get(2); + assertEquals("doubleProp", property.getPropertyName()); + assertEquals("D", property.getPropertyTypeDescriptor()); + assertFalse(property.isNullable()); + assertFalse(property.isPrimaryKeyMember()); + assertEquals(null, property.getAdapterTypeName()); + assertEquals(null, property.getAdapterParams()); + + property = properties.get(3); + assertEquals("intProp", property.getPropertyName()); + assertEquals("I", property.getPropertyTypeDescriptor()); + assertFalse(property.isNullable()); + assertFalse(property.isPrimaryKeyMember()); + assertEquals(null, property.getAdapterTypeName()); + assertEquals(null, property.getAdapterParams()); + + property = properties.get(4); + assertEquals("longProp", property.getPropertyName()); + assertEquals("J", property.getPropertyTypeDescriptor()); + assertFalse(property.isNullable()); + assertFalse(property.isPrimaryKeyMember()); + assertEquals(null, property.getAdapterTypeName()); + assertEquals(null, property.getAdapterParams()); + + property = properties.get(5); + assertEquals("stringProp", property.getPropertyName()); + assertEquals("Ljava/lang/String;", property.getPropertyTypeDescriptor()); + assertFalse(property.isNullable()); + assertFalse(property.isPrimaryKeyMember()); + assertEquals(null, property.getAdapterTypeName()); + assertEquals(null, property.getAdapterParams()); + } + } + + public void testAdapter() throws Exception { + // Run test twice: First time, records get inserted. Second time, they are loaded. + for (int i=0; i<2; i++) { + Layout layout = mFactory.layoutFor(FileInfo.class); + + assertEquals(FileInfo.class.getName(), layout.getStorableTypeName()); + + List properties = layout.getAllProperties(); + + // Should exclude joins. + assertEquals(8, properties.size()); + + LayoutProperty property; + + property = properties.get(1); + assertEquals("directory", property.getPropertyName()); + assertEquals("Z", property.getPropertyTypeDescriptor()); + assertFalse(property.isNullable()); + assertFalse(property.isPrimaryKeyMember()); + assertEquals(YesNoAdapter.class.getName(), property.getAdapterTypeName()); + assertEquals("@Lcom/amazon/carbonado/adapter/YesNoAdapter;lenient=Z1;", + property.getAdapterParams()); + } + } + + public void testAddProperty() throws Exception { + for (int i=0; i<2; i++) { + { + // Zero extra properties. + Class type = + defineStorable(TEST_STORABLE_NAME, 0, TypeDesc.INT); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME, layout.getStorableTypeName()); + assertEquals(0, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(1, properties.size()); + } + + { + // One extra property. + Class type = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.INT); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME, layout.getStorableTypeName()); + assertEquals(1, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(2, properties.size()); + assertEquals("prop0", properties.get(1).getPropertyName()); + assertEquals("I", properties.get(1).getPropertyTypeDescriptor()); + } + } + } + + public void testRemoveProperty() throws Exception { + for (int i=0; i<2; i++) { + { + // One extra property. + Class type = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.INT); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME, layout.getStorableTypeName()); + assertEquals(0, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(2, properties.size()); + assertEquals("prop0", properties.get(1).getPropertyName()); + assertEquals("I", properties.get(1).getPropertyTypeDescriptor()); + } + + { + // Zero extra properties. + Class type = + defineStorable(TEST_STORABLE_NAME, 0, TypeDesc.INT); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME, layout.getStorableTypeName()); + assertEquals(1, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(1, properties.size()); + } + } + } + + public void testChangePropertyType() throws Exception { + for (int i=0; i<2; i++) { + { + // One extra property, type int. + Class type = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.INT); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME, layout.getStorableTypeName()); + assertEquals(0, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(2, properties.size()); + assertEquals("prop0", properties.get(1).getPropertyName()); + assertEquals("I", properties.get(1).getPropertyTypeDescriptor()); + } + + { + // One extra property, type String. + Class type = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.STRING); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME, layout.getStorableTypeName()); + assertEquals(1, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(2, properties.size()); + assertEquals("prop0", properties.get(1).getPropertyName()); + assertEquals("Ljava/lang/String;", properties.get(1).getPropertyTypeDescriptor()); + } + } + } + + public void testWithMulipleTypes() throws Exception { + for (int i=0; i<10; i++) { + { + // One extra property, type int. + Class type = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.INT); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME, layout.getStorableTypeName()); + assertEquals(0, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(2, properties.size()); + assertEquals("prop0", properties.get(1).getPropertyName()); + assertEquals("I", properties.get(1).getPropertyTypeDescriptor()); + } + + { + // One extra property, type int. + Class type = + defineStorable(TEST_STORABLE_NAME_2, 1, TypeDesc.INT); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME_2, layout.getStorableTypeName()); + assertEquals(0, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(2, properties.size()); + assertEquals("prop0", properties.get(1).getPropertyName()); + assertEquals("I", properties.get(1).getPropertyTypeDescriptor()); + } + + { + // One extra property, type String. + Class type = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.STRING); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME, layout.getStorableTypeName()); + assertEquals(1, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(2, properties.size()); + assertEquals("prop0", properties.get(1).getPropertyName()); + assertEquals("Ljava/lang/String;", properties.get(1).getPropertyTypeDescriptor()); + } + + { + // One extra property, type String. + Class type = + defineStorable(TEST_STORABLE_NAME_2, 1, TypeDesc.STRING); + Layout layout = mFactory.layoutFor(type); + assertEquals(TEST_STORABLE_NAME_2, layout.getStorableTypeName()); + assertEquals(1, layout.getGeneration()); + List properties = layout.getAllProperties(); + assertEquals(2, properties.size()); + assertEquals("prop0", properties.get(1).getPropertyName()); + assertEquals("Ljava/lang/String;", properties.get(1).getPropertyTypeDescriptor()); + } + } + } + + public void testReconstruct() throws Exception { + // Run test twice: First time, records get inserted. Second time, they are loaded. + for (int i=0; i<2; i++) { + Layout layout = mFactory.layoutFor(StorableDateIndex.class); + + Class recon = layout.reconstruct(); + + assertTrue(recon != StorableDateIndex.class); + + Layout reconLayout = mFactory.layoutFor(recon); + assertTrue(layout == reconLayout); + + compareInfo(StorableIntrospector.examine(StorableDateIndex.class), + StorableIntrospector.examine(recon)); + } + } + + public void testEvolution_addProperties() throws Exception { + { + // Zero extra properties. + Class type = + defineStorable(TEST_STORABLE_NAME, 0, TypeDesc.INT); + Storage storage = mRepository.storageFor(type); + StorableTestMinimal stm = storage.prepare(); + stm.setId(1); + stm.insert(); + } + + { + // One extra property. + Class type = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.INT); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(type); + Storage storage = mRepository.storageFor(type); + StorableTestMinimal stm = storage.prepare(); + stm.setId(2); + bean.setPropertyValue(stm, "prop0", 200); + stm.insert(); + + // Now load old generation. + stm = storage.prepare(); + stm.setId(1); + stm.load(); + assertEquals(0, ((Integer) bean.getPropertyValue(stm, "prop0")).intValue()); + + // Verify load of new generation. + stm = storage.prepare(); + stm.setId(2); + stm.load(); + assertEquals(200, ((Integer) bean.getPropertyValue(stm, "prop0")).intValue()); + } + + { + // Two extra properties. + Class type = + defineStorable(TEST_STORABLE_NAME, 2, TypeDesc.INT); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(type); + Storage storage = mRepository.storageFor(type); + StorableTestMinimal stm = storage.prepare(); + stm.setId(3); + bean.setPropertyValue(stm, "prop0", 300); + bean.setPropertyValue(stm, "prop1", 301); + stm.insert(); + + // Now load old generations. + stm = storage.prepare(); + stm.setId(1); + stm.load(); + assertEquals(0, ((Integer) bean.getPropertyValue(stm, "prop0")).intValue()); + assertEquals(0, ((Integer) bean.getPropertyValue(stm, "prop1")).intValue()); + + stm = storage.prepare(); + stm.setId(2); + stm.load(); + assertEquals(200, ((Integer) bean.getPropertyValue(stm, "prop0")).intValue()); + assertEquals(0, ((Integer) bean.getPropertyValue(stm, "prop1")).intValue()); + + // Verify load of new generation. + stm = storage.prepare(); + stm.setId(3); + stm.load(); + assertEquals(300, ((Integer) bean.getPropertyValue(stm, "prop0")).intValue()); + assertEquals(301, ((Integer) bean.getPropertyValue(stm, "prop1")).intValue()); + } + + { + // Test incrementally with over 130 added properties, to ensure + // generation is encoded in 1 and 4 bytes formats. + for (int i=3; i<=130; i++) { + Class type = + defineStorable(TEST_STORABLE_NAME, i, TypeDesc.INT); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(type); + Storage storage = mRepository.storageFor(type); + StorableTestMinimal stm = storage.prepare(); + stm.setId(i + 3); + for (int j=0; j type = + defineStorable(TEST_STORABLE_NAME, 2, TypeDesc.INT); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(type); + Storage storage = mRepository.storageFor(type); + StorableTestMinimal stm = storage.prepare(); + stm.setId(1); + bean.setPropertyValue(stm, "prop0", 100); + bean.setPropertyValue(stm, "prop1", 101); + stm.insert(); + } + + { + // One extra property. + Class type = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.INT); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(type); + Storage storage = mRepository.storageFor(type); + StorableTestMinimal stm = storage.prepare(); + stm.setId(2); + bean.setPropertyValue(stm, "prop0", 200); + stm.insert(); + + // Now load old generation. + stm = storage.prepare(); + stm.setId(1); + stm.load(); + assertEquals(100, ((Integer) bean.getPropertyValue(stm, "prop0")).intValue()); + + // Verify load of new generation. + stm = storage.prepare(); + stm.setId(2); + stm.load(); + assertEquals(200, ((Integer) bean.getPropertyValue(stm, "prop0")).intValue()); + } + + { + // Zero extra properties. + Class type = + defineStorable(TEST_STORABLE_NAME, 0, TypeDesc.INT); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(type); + Storage storage = mRepository.storageFor(type); + StorableTestMinimal stm = storage.prepare(); + stm.setId(3); + stm.insert(); + + // Now load old generations. + stm = storage.prepare(); + stm.setId(1); + stm.load(); + + stm = storage.prepare(); + stm.setId(2); + stm.load(); + + // Verify load of new generation. + stm = storage.prepare(); + stm.setId(3); + stm.load(); + } + } + + public void testEvolution_changeProperties() throws Exception { + // Define various generations. + Class typeWithInt = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.INT); + Class typeWithStr = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.STRING); + Class typeWithLong = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.LONG); + Class typeWithDate = + defineStorable(TEST_STORABLE_NAME, 1, TypeDesc.forClass(DateTime.class)); + Class typeWithIntAndStr = + defineStorable(TEST_STORABLE_NAME, TypeDesc.INT, TypeDesc.STRING); + + DateTime date = new DateTime(); + + { + // Insert int prop0. + Storage storage = mRepository.storageFor(typeWithInt); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithInt); + StorableTestMinimal stm = storage.prepare(); + stm.setId(1); + bean.setPropertyValue(stm, "prop0", 100); + stm.insert(); + } + + { + // Insert String prop0. + Storage storage = mRepository.storageFor(typeWithStr); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithStr); + StorableTestMinimal stm = storage.prepare(); + stm.setId(2); + bean.setPropertyValue(stm, "prop0", "hello"); + stm.insert(); + } + + { + // Insert long prop0. + Storage storage = mRepository.storageFor(typeWithLong); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithLong); + StorableTestMinimal stm = storage.prepare(); + stm.setId(3); + bean.setPropertyValue(stm, "prop0", 0x100000001L); + stm.insert(); + } + + { + // Insert date prop0. + Storage storage = mRepository.storageFor(typeWithDate); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithDate); + StorableTestMinimal stm = storage.prepare(); + stm.setId(4); + bean.setPropertyValue(stm, "prop0", date); + stm.insert(); + } + + { + // Insert int prop0, String prop1. + Storage storage = + mRepository.storageFor(typeWithIntAndStr); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithIntAndStr); + StorableTestMinimal stm = storage.prepare(); + stm.setId(5); + bean.setPropertyValue(stm, "prop0", 500); + bean.setPropertyValue(stm, "prop1", "world"); + stm.insert(); + } + + // Load using int property generation. + { + // Load against int prop0. + Storage storage = mRepository.storageFor(typeWithInt); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithInt); + StorableTestMinimal stm = storage.prepare(); + stm.setId(1); + stm.load(); + assertEquals(100, bean.getPropertyValue(stm, "prop0")); + + // Load against String prop0. + stm = storage.prepare(); + stm.setId(2); + stm.load(); + assertEquals(0, bean.getPropertyValue(stm, "prop0")); + + // Load against long prop0. + stm = storage.prepare(); + stm.setId(3); + stm.load(); + // Cast of 0x100000001L to int yields 1. + assertEquals(1, bean.getPropertyValue(stm, "prop0")); + + // Load against date prop0. + stm = storage.prepare(); + stm.setId(4); + stm.load(); + assertEquals(0, bean.getPropertyValue(stm, "prop0")); + + // Load against int prop0, String prop1. + stm = storage.prepare(); + stm.setId(5); + stm.load(); + assertEquals(500, bean.getPropertyValue(stm, "prop0")); + } + + // Load using String property generation. + { + // Load against int prop0. + Storage storage = mRepository.storageFor(typeWithStr); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithStr); + StorableTestMinimal stm = storage.prepare(); + stm.setId(1); + stm.load(); + assertEquals(null, bean.getPropertyValue(stm, "prop0")); + + // Load against String prop0. + stm = storage.prepare(); + stm.setId(2); + stm.load(); + assertEquals("hello", bean.getPropertyValue(stm, "prop0")); + + // Load against long prop0. + stm = storage.prepare(); + stm.setId(3); + stm.load(); + assertEquals(null, bean.getPropertyValue(stm, "prop0")); + + // Load against date prop0. + stm = storage.prepare(); + stm.setId(4); + stm.load(); + assertEquals(null, bean.getPropertyValue(stm, "prop0")); + + // Load against int prop0, String prop1. + stm = storage.prepare(); + stm.setId(5); + stm.load(); + assertEquals(null, bean.getPropertyValue(stm, "prop0")); + } + + // Load using long property generation. + { + // Load against int prop0. + Storage storage = mRepository.storageFor(typeWithLong); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithLong); + StorableTestMinimal stm = storage.prepare(); + stm.setId(1); + stm.load(); + assertEquals(100L, bean.getPropertyValue(stm, "prop0")); + + // Load against String prop0. + stm = storage.prepare(); + stm.setId(2); + stm.load(); + assertEquals(0L, bean.getPropertyValue(stm, "prop0")); + + // Load against long prop0. + stm = storage.prepare(); + stm.setId(3); + stm.load(); + assertEquals(0x100000001L, bean.getPropertyValue(stm, "prop0")); + + // Load against date prop0. + stm = storage.prepare(); + stm.setId(4); + stm.load(); + assertEquals(0L, bean.getPropertyValue(stm, "prop0")); + + // Load against int prop0, String prop1. + stm = storage.prepare(); + stm.setId(5); + stm.load(); + assertEquals(500L, bean.getPropertyValue(stm, "prop0")); + } + + // Load using date property generation. + { + // Load against int prop0. + Storage storage = mRepository.storageFor(typeWithDate); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithDate); + StorableTestMinimal stm = storage.prepare(); + stm.setId(1); + stm.load(); + assertEquals(null, bean.getPropertyValue(stm, "prop0")); + + // Load against String prop0. + stm = storage.prepare(); + stm.setId(2); + stm.load(); + assertEquals(null, bean.getPropertyValue(stm, "prop0")); + + // Load against long prop0. + stm = storage.prepare(); + stm.setId(3); + stm.load(); + assertEquals(null, bean.getPropertyValue(stm, "prop0")); + + // Load against date prop0. + stm = storage.prepare(); + stm.setId(4); + stm.load(); + assertEquals(date, bean.getPropertyValue(stm, "prop0")); + + // Load against int prop0, String prop1. + stm = storage.prepare(); + stm.setId(5); + stm.load(); + assertEquals(null, bean.getPropertyValue(stm, "prop0")); + } + + // Load using int and String property generation. + { + // Load against int prop0. + Storage storage = + mRepository.storageFor(typeWithIntAndStr); + BeanPropertyAccessor bean = BeanPropertyAccessor.forClass(typeWithIntAndStr); + StorableTestMinimal stm = storage.prepare(); + stm.setId(1); + stm.load(); + assertEquals(100, bean.getPropertyValue(stm, "prop0")); + assertEquals(null, bean.getPropertyValue(stm, "prop1")); + + // Load against String prop0. + stm = storage.prepare(); + stm.setId(2); + stm.load(); + assertEquals(0, bean.getPropertyValue(stm, "prop0")); + assertEquals(null, bean.getPropertyValue(stm, "prop1")); + + // Load against long prop0. + stm = storage.prepare(); + stm.setId(3); + stm.load(); + // Cast of 0x100000001L to int yields 1. + assertEquals(1, bean.getPropertyValue(stm, "prop0")); + assertEquals(null, bean.getPropertyValue(stm, "prop1")); + + // Load against date prop0. + stm = storage.prepare(); + stm.setId(4); + stm.load(); + assertEquals(0, bean.getPropertyValue(stm, "prop0")); + assertEquals(null, bean.getPropertyValue(stm, "prop1")); + + // Load against int prop0, String prop1. + stm = storage.prepare(); + stm.setId(5); + stm.load(); + assertEquals(500, bean.getPropertyValue(stm, "prop0")); + assertEquals("world", bean.getPropertyValue(stm, "prop1")); + } + } + + private void compareInfo(StorableInfo expected, StorableInfo actual) { + Map expectedProps = expected.getAllProperties(); + Map actualProps = actual.getAllProperties(); + + for (StorableProperty expectedProp : expectedProps.values()) { + StorableProperty actualProp = actualProps.get(expectedProp.getName()); + if (actualProp == null) { + fail("Missing property: " + expectedProp.getName()); + } + assertEquals(expectedProp.getType(), actualProp.getType()); + + assertEquals(expectedProp.isPrimaryKeyMember(), actualProp.isPrimaryKeyMember()); + + StorablePropertyAdapter expectedAdapter = expectedProp.getAdapter(); + StorablePropertyAdapter actualAdapter = actualProp.getAdapter(); + + if (expectedAdapter == null) { + assertNull(actualAdapter); + } else { + assertNotNull(actualAdapter); + assertEquals(expectedAdapter.getAnnotation().getAnnotation(), + actualAdapter.getAnnotation().getAnnotation()); + } + } + } + + private Class defineStorable(String name, + int extraPropCount, + TypeDesc propType) + { + ClassInjector ci = ClassInjector.createExplicit(name, null); + ClassFile cf = new ClassFile(ci.getClassName()); + cf.setTarget("1.5"); + cf.setModifiers(cf.getModifiers().toInterface(true)); + cf.addInterface(StorableTestMinimal.class); + + definePrimaryKey(cf); + + for (int i=0; i defineStorable(String name, + TypeDesc propType, + TypeDesc propType2) + { + ClassInjector ci = ClassInjector.createExplicit(name, null); + ClassFile cf = new ClassFile(ci.getClassName()); + cf.setTarget("1.5"); + cf.setModifiers(cf.getModifiers().toInterface(true)); + cf.addInterface(StorableTestMinimal.class); + + definePrimaryKey(cf); + + int i = 0; + cf.addMethod(Modifiers.PUBLIC_ABSTRACT, "getProp" + i, propType, null); + cf.addMethod(Modifiers.PUBLIC_ABSTRACT, "setProp" + i, null, new TypeDesc[]{propType}); + + i++; + cf.addMethod(Modifiers.PUBLIC_ABSTRACT, "getProp" + i, propType2, null); + cf.addMethod(Modifiers.PUBLIC_ABSTRACT, "setProp" + i, null, new TypeDesc[]{propType2}); + + return ci.defineClass(cf); + } + + private void definePrimaryKey(ClassFile cf) { + // Add primary key on inherited "id" property. + // @PrimaryKey(value={"id"}) + Annotation pk = cf.addRuntimeVisibleAnnotation(TypeDesc.forClass(PrimaryKey.class)); + Annotation.MemberValue[] props = new Annotation.MemberValue[1]; + props[0] = pk.makeMemberValue("id"); + pk.putMemberValue("value", props); + } +} -- cgit v1.2.3