/*-
* 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.assertEquals;
import static org.junit.Assert.assertTrue;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.sleepycat.persist.evolve.EvolveConfig;
import com.sleepycat.persist.evolve.EvolveEvent;
import com.sleepycat.persist.evolve.EvolveListener;
import com.sleepycat.persist.evolve.EvolveStats;
import com.sleepycat.persist.impl.PersistCatalog;
import com.sleepycat.util.test.SharedTestUtils;
/**
* Runs part two of the EvolveTest. This part is run with the new/updated
* version of EvolveClasses in the classpath. It uses the environment and
* store created by EvolveTestInit. It verifies that it can read/write/evolve
* objects serialized using the old class format, and that it can create new
* objects with the new class format.
*
* @author Mark Hayes
*/
public class EvolveTest extends EvolveTestBase {
public EvolveTest(String originalClsName, String evolvedClsName)
throws Exception {
super(originalClsName, evolvedClsName);
}
/* Toggle to use listener every other test case. */
private static boolean useEvolveListener;
private int evolveNRead;
private int evolveNConverted;
boolean useEvolvedClass() {
return true;
}
@Before
public void setUp()
throws Exception {
super.setUp();
/* Copy the log files created by EvolveTestInit. */
envHome = getTestInitHome(true /*evolved*/);
envHome.mkdirs();
SharedTestUtils.emptyDir(envHome);
SharedTestUtils.copyFiles(getTestInitHome(false /*evolved*/), envHome);
}
@After
public void tearDown() {
try { super.tearDown(); } catch (Throwable e) { }
}
@Test
public void testLazyEvolve()
throws Exception {
openEnv();
/*
* Open in raw mode to check unevolved raw object and formats. This
* is possible whether or not we can open the store further below to
* evolve formats without errors.
*/
openRawStore();
caseObj.checkUnevolvedModel(rawStore.getModel(), env);
caseObj.readRawObjects
(rawStore, false /*expectEvolved*/, false /*expectUpdated*/);
closeRawStore();
/*
* Check evolution in read-only mode. Since Replica upgrade mode is
* effectively read-only mode, this also helps to test evolution during
* replication group upgrades. [#18690]
*/
if (openStoreReadOnly()) {
caseObj.checkEvolvedModel
(store.getModel(), env, true /*oldTypesExist*/);
caseObj.readObjects(store, false /*doUpdate*/);
closeStore();
}
if (openStoreReadWrite()) {
/*
* When opening read-write, formats are evolved lazily. Check by
* reading evolved objects.
*/
caseObj.checkEvolvedModel
(store.getModel(), env, true /*oldTypesExist*/);
caseObj.readObjects(store, false /*doUpdate*/);
closeStore();
/*
* Read raw objects again to check that the evolved objects are
* returned even though the stored objects were not evolved.
*/
openRawStore();
caseObj.checkEvolvedModel
(rawStore.getModel(), env, true /*oldTypesExist*/);
caseObj.readRawObjects
(rawStore, true /*expectEvolved*/, false /*expectUpdated*/);
closeRawStore();
/*
* Open read-only to ensure that the catalog does not need to
* change (evolve formats) unnecessarily.
*/
PersistCatalog.expectNoClassChanges = true;
try {
assertTrue(openStoreReadOnly());
} finally {
PersistCatalog.expectNoClassChanges = false;
}
caseObj.checkEvolvedModel
(store.getModel(), env, true /*oldTypesExist*/);
caseObj.readObjects(store, false /*doUpdate*/);
closeStore();
/*
* Open read-write to update objects and store them in evolved
* format.
*/
openStoreReadWrite();
caseObj.checkEvolvedModel
(store.getModel(), env, true /*oldTypesExist*/);
caseObj.readObjects(store, true /*doUpdate*/);
caseObj.checkEvolvedModel
(store.getModel(), env, true /*oldTypesExist*/);
closeStore();
/*
* Check raw objects again after the evolved objects were stored.
*/
openRawStore();
caseObj.checkEvolvedModel
(rawStore.getModel(), env, true /*oldTypesExist*/);
caseObj.readRawObjects
(rawStore, true /*expectEvolved*/, true /*expectUpdated*/);
closeRawStore();
}
closeAll();
}
@Test
public void testEagerEvolve()
throws Exception {
/* If the store cannot be opened, this test is not appropriate. */
if (caseObj.getStoreOpenException() != null) {
return;
}
EvolveConfig config = new EvolveConfig();
/*
* Use listener every other time to ensure that the stats are returned
* correctly when no listener is configured. [#17024]
*/
useEvolveListener = !useEvolveListener;
if (useEvolveListener) {
config.setEvolveListener(new EvolveListener() {
public boolean evolveProgress(EvolveEvent event) {
EvolveStats stats = event.getStats();
evolveNRead = stats.getNRead();
evolveNConverted = stats.getNConverted();
return true;
}
});
}
openEnv();
openStoreReadWrite();
/*
* Evolve and expect that the expected number of entities are
* converted.
*/
int nExpected = caseObj.getNRecordsExpected();
evolveNRead = 0;
evolveNConverted = 0;
PersistCatalog.unevolvedFormatsEncountered = false;
EvolveStats stats = store.evolve(config);
if (nExpected > 0) {
assertTrue(PersistCatalog.unevolvedFormatsEncountered);
}
assertTrue(stats.getNRead() == nExpected);
assertTrue(stats.getNConverted() == nExpected);
assertTrue(stats.getNConverted() >= stats.getNRead());
if (useEvolveListener) {
assertEquals(evolveNRead, stats.getNRead());
assertEquals(evolveNConverted, stats.getNConverted());
}
/* Evolve again and expect that no entities are converted. */
evolveNRead = 0;
evolveNConverted = 0;
PersistCatalog.unevolvedFormatsEncountered = false;
stats = store.evolve(config);
assertTrue(!PersistCatalog.unevolvedFormatsEncountered);
assertEquals(0, stats.getNRead());
assertEquals(0, stats.getNConverted());
if (useEvolveListener) {
assertTrue(evolveNRead == 0);
assertTrue(evolveNConverted == 0);
}
/* Ensure that we can read all entities without evolution. */
PersistCatalog.unevolvedFormatsEncountered = false;
caseObj.readObjects(store, false /*doUpdate*/);
assertTrue(!PersistCatalog.unevolvedFormatsEncountered);
/*
* When automatic unused type deletion is implemented in the future the
* oldTypesExist parameters below should be changed to false.
*/
/* Open again and try an update. */
caseObj.checkEvolvedModel
(store.getModel(), env, true /*oldTypesExist*/);
caseObj.readObjects(store, true /*doUpdate*/);
caseObj.checkEvolvedModel
(store.getModel(), env, true /*oldTypesExist*/);
closeStore();
/* Open read-only and double check that everything is OK. */
assertTrue(openStoreReadOnly());
caseObj.checkEvolvedModel
(store.getModel(), env, true /*oldTypesExist*/);
caseObj.readObjects(store, false /*doUpdate*/);
caseObj.checkEvolvedModel
(store.getModel(), env, true /*oldTypesExist*/);
closeStore();
/* Check raw objects. */
openRawStore();
caseObj.checkEvolvedModel
(rawStore.getModel(), env, true /*oldTypesExist*/);
caseObj.readRawObjects
(rawStore, true /*expectEvolved*/, true /*expectUpdated*/);
/*
* Test copy raw object to new store via convertRawObject. In this
* test we can pass false for oldTypesExist because newStore starts
* with the new/evolved class model.
*/
openNewStore();
caseObj.copyRawObjects(rawStore, newStore);
caseObj.readObjects(newStore, true /*doUpdate*/);
caseObj.checkEvolvedModel
(newStore.getModel(), env, false /*oldTypesExist*/);
closeNewStore();
closeRawStore();
closeAll();
}
}