1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2000, 2010 Oracle and/or its affiliates.  All rights reserved.
5  *
6  */
7 package com.sleepycat.persist.test;
8 
9 import static org.junit.Assert.assertEquals;
10 import static org.junit.Assert.assertTrue;
11 
12 import org.junit.After;
13 import org.junit.Before;
14 import org.junit.Test;
15 
16 import com.sleepycat.persist.evolve.EvolveConfig;
17 import com.sleepycat.persist.evolve.EvolveEvent;
18 import com.sleepycat.persist.evolve.EvolveListener;
19 import com.sleepycat.persist.evolve.EvolveStats;
20 import com.sleepycat.persist.impl.PersistCatalog;
21 import com.sleepycat.util.test.SharedTestUtils;
22 
23 /**
24  * Runs part two of the EvolveTest.  This part is run with the new/updated
25  * version of EvolveClasses in the classpath.  It uses the environment and
26  * store created by EvolveTestInit.  It verifies that it can read/write/evolve
27  * objects serialized using the old class format, and that it can create new
28  * objects with the new class format.
29  *
30  * @author Mark Hayes
31  */
32 public class EvolveTest extends EvolveTestBase {
33 
EvolveTest(String originalClsName, String evolvedClsName)34     public EvolveTest(String originalClsName, String evolvedClsName)
35             throws Exception {
36         super(originalClsName, evolvedClsName);
37     }
38 
39     /* Toggle to use listener every other test case. */
40     private static boolean useEvolveListener;
41 
42     private int evolveNRead;
43     private int evolveNConverted;
44 
useEvolvedClass()45     boolean useEvolvedClass() {
46         return true;
47     }
48 
49     @Before
setUp()50     public void setUp()
51         throws Exception {
52 
53         super.setUp();
54 
55         /* Copy the log files created by EvolveTestInit. */
56         envHome = getTestInitHome(true /*evolved*/);
57         envHome.mkdirs();
58         SharedTestUtils.emptyDir(envHome);
59         SharedTestUtils.copyFiles(getTestInitHome(false /*evolved*/), envHome);
60     }
61 
62     @After
tearDown()63     public void tearDown() {
64         try { super.tearDown(); } catch (Throwable e) { }
65     }
66 
67     @Test
testLazyEvolve()68     public void testLazyEvolve()
69         throws Exception {
70 
71         openEnv();
72 
73         /*
74          * Open in raw mode to check unevolved raw object and formats.  This
75          * is possible whether or not we can open the store further below to
76          * evolve formats without errors.
77          */
78         openRawStore();
79         caseObj.checkUnevolvedModel(rawStore.getModel(), env);
80         caseObj.readRawObjects
81             (rawStore, false /*expectEvolved*/, false /*expectUpdated*/);
82         closeRawStore();
83 
84         /*
85          * Check evolution in read-only mode. Since Replica upgrade mode is
86          * effectively read-only mode, this also helps to test evolution during
87          * replication group upgrades. [#18690]
88          */
89         if (openStoreReadOnly()) {
90             caseObj.checkEvolvedModel
91                 (store.getModel(), env, true /*oldTypesExist*/);
92             caseObj.readObjects(store, false /*doUpdate*/);
93             closeStore();
94         }
95 
96         if (openStoreReadWrite()) {
97 
98             /*
99              * When opening read-write, formats are evolved lazily.  Check by
100              * reading evolved objects.
101              */
102             caseObj.checkEvolvedModel
103                 (store.getModel(), env, true /*oldTypesExist*/);
104             caseObj.readObjects(store, false /*doUpdate*/);
105             closeStore();
106 
107             /*
108              * Read raw objects again to check that the evolved objects are
109              * returned even though the stored objects were not evolved.
110              */
111             openRawStore();
112             caseObj.checkEvolvedModel
113                 (rawStore.getModel(), env, true /*oldTypesExist*/);
114             caseObj.readRawObjects
115                 (rawStore, true /*expectEvolved*/, false /*expectUpdated*/);
116             closeRawStore();
117 
118             /*
119              * Open read-only to ensure that the catalog does not need to
120              * change (evolve formats) unnecessarily.
121              */
122             PersistCatalog.expectNoClassChanges = true;
123             try {
124                 assertTrue(openStoreReadOnly());
125             } finally {
126                 PersistCatalog.expectNoClassChanges = false;
127             }
128             caseObj.checkEvolvedModel
129                 (store.getModel(), env, true /*oldTypesExist*/);
130             caseObj.readObjects(store, false /*doUpdate*/);
131             closeStore();
132 
133             /*
134              * Open read-write to update objects and store them in evolved
135              * format.
136              */
137             openStoreReadWrite();
138             caseObj.checkEvolvedModel
139                 (store.getModel(), env, true /*oldTypesExist*/);
140             caseObj.readObjects(store, true /*doUpdate*/);
141             caseObj.checkEvolvedModel
142                 (store.getModel(), env, true /*oldTypesExist*/);
143             closeStore();
144 
145             /*
146              * Check raw objects again after the evolved objects were stored.
147              */
148             openRawStore();
149             caseObj.checkEvolvedModel
150                 (rawStore.getModel(), env, true /*oldTypesExist*/);
151             caseObj.readRawObjects
152                 (rawStore, true /*expectEvolved*/, true /*expectUpdated*/);
153             closeRawStore();
154         }
155 
156         closeAll();
157     }
158 
159     @Test
testEagerEvolve()160     public void testEagerEvolve()
161         throws Exception {
162 
163         /* If the store cannot be opened, this test is not appropriate. */
164         if (caseObj.getStoreOpenException() != null) {
165             return;
166         }
167 
168         EvolveConfig config = new EvolveConfig();
169 
170         /*
171          * Use listener every other time to ensure that the stats are returned
172          * correctly when no listener is configured. [#17024]
173          */
174         useEvolveListener = !useEvolveListener;
175         if (useEvolveListener) {
176             config.setEvolveListener(new EvolveListener() {
177                 public boolean evolveProgress(EvolveEvent event) {
178                     EvolveStats stats = event.getStats();
179                     evolveNRead = stats.getNRead();
180                     evolveNConverted = stats.getNConverted();
181                     return true;
182                 }
183             });
184         }
185 
186         openEnv();
187 
188         openStoreReadWrite();
189 
190         /*
191          * Evolve and expect that the expected number of entities are
192          * converted.
193          */
194         int nExpected = caseObj.getNRecordsExpected();
195         evolveNRead = 0;
196         evolveNConverted = 0;
197         PersistCatalog.unevolvedFormatsEncountered = false;
198         EvolveStats stats = store.evolve(config);
199         if (nExpected > 0) {
200             assertTrue(PersistCatalog.unevolvedFormatsEncountered);
201         }
202         assertTrue(stats.getNRead() == nExpected);
203         assertTrue(stats.getNConverted() == nExpected);
204         assertTrue(stats.getNConverted() >= stats.getNRead());
205         if (useEvolveListener) {
206             assertEquals(evolveNRead, stats.getNRead());
207             assertEquals(evolveNConverted, stats.getNConverted());
208         }
209 
210         /* Evolve again and expect that no entities are converted. */
211         evolveNRead = 0;
212         evolveNConverted = 0;
213         PersistCatalog.unevolvedFormatsEncountered = false;
214         stats = store.evolve(config);
215         assertTrue(!PersistCatalog.unevolvedFormatsEncountered);
216         assertEquals(0, stats.getNRead());
217         assertEquals(0, stats.getNConverted());
218         if (useEvolveListener) {
219             assertTrue(evolveNRead == 0);
220             assertTrue(evolveNConverted == 0);
221         }
222 
223         /* Ensure that we can read all entities without evolution. */
224         PersistCatalog.unevolvedFormatsEncountered = false;
225         caseObj.readObjects(store, false /*doUpdate*/);
226         assertTrue(!PersistCatalog.unevolvedFormatsEncountered);
227 
228         /*
229          * When automatic unused type deletion is implemented in the future the
230          * oldTypesExist parameters below should be changed to false.
231          */
232 
233         /* Open again and try an update. */
234         caseObj.checkEvolvedModel
235             (store.getModel(), env, true /*oldTypesExist*/);
236         caseObj.readObjects(store, true /*doUpdate*/);
237         caseObj.checkEvolvedModel
238             (store.getModel(), env, true /*oldTypesExist*/);
239         closeStore();
240 
241         /* Open read-only and double check that everything is OK. */
242         assertTrue(openStoreReadOnly());
243         caseObj.checkEvolvedModel
244             (store.getModel(), env, true /*oldTypesExist*/);
245         caseObj.readObjects(store, false /*doUpdate*/);
246         caseObj.checkEvolvedModel
247             (store.getModel(), env, true /*oldTypesExist*/);
248         closeStore();
249 
250         /* Check raw objects. */
251         openRawStore();
252         caseObj.checkEvolvedModel
253             (rawStore.getModel(), env, true /*oldTypesExist*/);
254         caseObj.readRawObjects
255             (rawStore, true /*expectEvolved*/, true /*expectUpdated*/);
256 
257         /*
258          * Test copy raw object to new store via convertRawObject.  In this
259          * test we can pass false for oldTypesExist because newStore starts
260          * with the new/evolved class model.
261          */
262         openNewStore();
263         caseObj.copyRawObjects(rawStore, newStore);
264         caseObj.readObjects(newStore, true /*doUpdate*/);
265         caseObj.checkEvolvedModel
266             (newStore.getModel(), env, false /*oldTypesExist*/);
267         closeNewStore();
268         closeRawStore();
269 
270         closeAll();
271     }
272 }
273