/*- * See the file LICENSE for redistribution information. * * Copyright (c) 2000, 2015 Oracle and/or its affiliates. All rights reserved. * */ package com.sleepycat.persist.test; import static org.junit.Assert.fail; import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import org.junit.After; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; import com.sleepycat.db.DatabaseException; import com.sleepycat.db.Environment; import com.sleepycat.db.EnvironmentConfig; import com.sleepycat.persist.EntityStore; import com.sleepycat.persist.StoreConfig; import com.sleepycat.persist.evolve.IncompatibleClassException; import com.sleepycat.persist.model.AnnotationModel; import com.sleepycat.persist.model.EntityModel; import com.sleepycat.persist.raw.RawStore; import com.sleepycat.util.test.TestBase; import com.sleepycat.util.test.TestEnv; /** * Base class for EvolveTest and EvolveTestInit. * * @author Mark Hayes */ @RunWith(Parameterized.class) public abstract class EvolveTestBase extends TestBase { /* * When adding a evolve test class, three places need to be changed: * 1) Add the unmodified class to EvolveClass.java.original. * 2) Add the modified class to EvolveClass.java. * 3) Add the class name to the ALL list below as a pair of strings. The * first string in each pair is the name of the original class, and the * second string is the name of the evolved class or null if the evolved * name is the same as the original. The index in the list identifies a * test case, and the class at that position identifies the old and new * class to use for the test. */ private static final String[] ALL = { //* "DeletedEntity1_ClassRemoved", "DeletedEntity1_ClassRemoved_NoMutation", "DeletedEntity2_ClassRemoved", "DeletedEntity2_ClassRemoved_WithDeleter", "DeletedEntity3_AnnotRemoved_NoMutation", null, "DeletedEntity4_AnnotRemoved_WithDeleter", null, "DeletedEntity5_EntityToPersist_NoMutation", null, "DeletedEntity6_EntityToPersist_WithDeleter", null, "DeletedPersist1_ClassRemoved_NoMutation", null, "DeletedPersist2_ClassRemoved_WithDeleter", null, "DeletedPersist3_AnnotRemoved_NoMutation", null, "DeletedPersist4_AnnotRemoved_WithDeleter", null, "DeletedPersist5_PersistToEntity_NoMutation", null, "DeletedPersist6_PersistToEntity_WithDeleter", null, "RenamedEntity1_NewEntityName", "RenamedEntity1_NewEntityName_NoMutation", "RenamedEntity2_NewEntityName", "RenamedEntity2_NewEntityName_WithRenamer", "DeleteSuperclass1_NoMutation", null, "DeleteSuperclass2_WithConverter", null, "DeleteSuperclass3_WithDeleter", null, "DeleteSuperclass4_NoFields", null, "DeleteSuperclass5_Top", null, "InsertSuperclass1_Between", null, "InsertSuperclass2_Top", null, "DisallowNonKeyField_PrimitiveToObject", null, "DisallowNonKeyField_ObjectToPrimitive", null, "DisallowNonKeyField_ObjectToSubtype", null, "DisallowNonKeyField_ObjectToUnrelatedSimple", null, "DisallowNonKeyField_ObjectToUnrelatedOther", null, "DisallowNonKeyField_byte2boolean", null, "DisallowNonKeyField_short2byte", null, "DisallowNonKeyField_int2short", null, "DisallowNonKeyField_long2int", null, "DisallowNonKeyField_float2long", null, "DisallowNonKeyField_double2float", null, "DisallowNonKeyField_Byte2byte", null, "DisallowNonKeyField_Character2char", null, "DisallowNonKeyField_Short2short", null, "DisallowNonKeyField_Integer2int", null, "DisallowNonKeyField_Long2long", null, "DisallowNonKeyField_Float2float", null, "DisallowNonKeyField_Double2double", null, "DisallowNonKeyField_float2BigInt", null, "DisallowNonKeyField_BigInt2long", null, "DisallowSecKeyField_byte2short", null, "DisallowSecKeyField_char2int", null, "DisallowSecKeyField_short2int", null, "DisallowSecKeyField_int2long", null, "DisallowSecKeyField_long2float", null, "DisallowSecKeyField_float2double", null, "DisallowSecKeyField_Byte2short2", null, "DisallowSecKeyField_Character2int", null, "DisallowSecKeyField_Short2int2", null, "DisallowSecKeyField_Integer2long", null, "DisallowSecKeyField_Long2float2", null, "DisallowSecKeyField_Float2double2", null, "DisallowSecKeyField_int2BigInt", null, "DisallowPriKeyField_byte2short", null, "DisallowPriKeyField_char2int", null, "DisallowPriKeyField_short2int", null, "DisallowPriKeyField_int2long", null, "DisallowPriKeyField_long2float", null, "DisallowPriKeyField_float2double", null, "DisallowPriKeyField_Byte2short2", null, "DisallowPriKeyField_Character2int", null, "DisallowPriKeyField_Short2int2", null, "DisallowPriKeyField_Integer2long", null, "DisallowPriKeyField_Long2float2", null, "DisallowPriKeyField_Float2double2", null, "DisallowPriKeyField_Long2BigInt", null, "DisallowCompositeKeyField_byte2short", null, "AllowPriKeyField_Byte2byte2", null, "AllowPriKeyField_byte2Byte", null, "AllowFieldTypeChanges", null, "ConvertFieldContent_Entity", null, "ConvertExample1_Entity", null, "ConvertExample2_Person", null, "ConvertExample3_Person", null, "ConvertExample3Reverse_Person", null, "ConvertExample4_Entity", null, "ConvertExample5_Entity", null, "AllowFieldAddDelete", null, "ProxiedClass_Entity", null, "DisallowChangeProxyFor", null, "DisallowDeleteProxyFor", null, "ArrayNameChange_Entity", null, "AddEnumConstant_Entity", null, "InsertEnumConstant_Entity", null, "DeleteEnumConstant_NoMutation", null, "DisallowChangeKeyRelate", null, "AllowChangeKeyMetadata", null, "AllowChangeKeyMetadataInSubclass", null, "AllowAddSecondary", null, "FieldAddAndConvert", null, "RenameSecFieldDestroyOrder_1", null, "RenameSecFieldDestroyOrder_2", null, "RenameSecFieldDestroyOrder_3", null, "DeleteSecAnnotationDestroyOrder", null, "ProxyClassFieldChanged", null, "ProxyClassObjectFieldChanged", null, "ProxyClassArrayFieldChanged", null, "ProxyClassObjectArrayFieldChanged", null, "MultipleSelfRefs", null, //*/ }; File envHome; Environment env; EntityStore store; RawStore rawStore; EntityStore newStore; String caseClsName; Class caseCls; EvolveCase caseObj; String caseLabel; @Parameters public static List<Object[]> genParams() { return paramsHelper(); } protected static List<Object[]> paramsHelper() { List<Object[]> list = new ArrayList<Object[]>(); for (int i = 0; i < ALL.length; i += 2) { if (ALL[i+1] == null) { list.add(new Object[]{ALL[i], ALL[i]}); } else { list.add(new Object[]{ALL[i], ALL[i+1]}); } } return list; } public EvolveTestBase(String originalClsName, String evolvedClsName) throws Exception{ String caseClsName = useEvolvedClass() ? evolvedClsName : originalClsName; caseClsName = "com.sleepycat.persist.test.EvolveClasses$" + caseClsName; this.caseClsName = caseClsName; this.caseCls = Class.forName(caseClsName); this.caseObj = (EvolveCase) caseCls.newInstance(); this.caseLabel = evolvedClsName; customName = "-" + caseLabel; } abstract boolean useEvolvedClass(); File getTestInitHome(boolean evolved) { return new File (System.getProperty("testevolvedir"), (evolved ? "evolved" : "original") + '/' + caseLabel); } @After public void tearDown() { if (env != null) { try { closeAll(); } catch (Throwable e) { System.out.println("During tearDown: " + e); } } envHome = null; env = null; store = null; caseCls = null; caseObj = null; caseLabel = null; /* Do not delete log files so they can be used by 2nd phase of test. */ } /** * @throws FileNotFoundException from DB core. */ void openEnv() throws FileNotFoundException, DatabaseException { EnvironmentConfig config = TestEnv.TXN.getConfig(); config.setAllowCreate(true); env = new Environment(envHome, config); } /** * Returns true if the store was opened successfully. Returns false if the * store could not be opened because an exception was expected -- this is * not a test failure but no further tests for an EntityStore may be run. */ private boolean openStore(StoreConfig config) throws Exception { config.setTransactional(true); config.setMutations(caseObj.getMutations()); EntityModel model = new AnnotationModel(); config.setModel(model); caseObj.configure(model, config); String expectException = caseObj.getStoreOpenException(); try { store = new EntityStore(env, EvolveCase.STORE_NAME, config); if (expectException != null) { fail("Expected: " + expectException); } } catch (Exception e) { if (expectException != null) { String actualMsg = e.getMessage(); if (e instanceof IncompatibleClassException) { actualMsg = actualMsg.substring (0, actualMsg.lastIndexOf("\n---\n(Note that")); } actualMsg = e.getClass().getName() + ": " + actualMsg; if (!expectException.equals(actualMsg)) { e.printStackTrace(); } EvolveCase.checkEquals(expectException, actualMsg); return false; } else { throw e; } } return true; } boolean openStoreReadOnly() throws Exception { StoreConfig config = new StoreConfig(); config.setReadOnly(true); return openStore(config); } boolean openStoreReadWrite() throws Exception { StoreConfig config = new StoreConfig(); config.setAllowCreate(true); final boolean retVal = openStore(config); if (retVal) { caseObj.newMetadataWritten = true; } return retVal; } void openRawStore() throws DatabaseException { StoreConfig config = new StoreConfig(); config.setTransactional(true); rawStore = new RawStore(env, EvolveCase.STORE_NAME, config); } void closeStore() throws DatabaseException { if (store != null) { store.close(); store = null; } } void openNewStore() throws Exception { StoreConfig config = new StoreConfig(); config.setAllowCreate(true); config.setTransactional(true); EntityModel model = new AnnotationModel(); config.setModel(model); caseObj.configure(model, config); newStore = new EntityStore(env, "new", config); } void closeNewStore() throws DatabaseException { if (newStore != null) { newStore.close(); newStore = null; } } void closeRawStore() throws DatabaseException { if (rawStore != null) { rawStore.close(); rawStore = null; } } void closeEnv() throws DatabaseException { if (env != null) { env.close(); env = null; } } void closeAll() throws DatabaseException { closeStore(); closeRawStore(); closeNewStore(); closeEnv(); } }