KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > triactive > jdo > test > StorageTestCase


1 /*
2  * Copyright 2004 (C) TJDO.
3  * All rights reserved.
4  *
5  * This software is distributed under the terms of the TJDO License version 1.0.
6  * See the terms of the TJDO License in the documentation provided with this software.
7  *
8  * $Id: StorageTestCase.java,v 1.7 2004/01/18 03:01:07 jackknifebarber Exp $
9  */

10
11 package com.triactive.jdo.test;
12
13 import java.util.Collection JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.Random JavaDoc;
17 import java.util.Set JavaDoc;
18 import javax.jdo.Extent;
19 import javax.jdo.JDOHelper;
20 import javax.jdo.PersistenceManager;
21 import javax.jdo.Transaction;
22 import org.apache.log4j.Category;
23
24
25 /**
26  * Abstract base class for all JDO unit tests that perform tests on objects
27  * derived from {@link TestObject}. Provides functions to create, update,
28  * validate, and remove such objects.
29  *
30  * @author <a HREF="mailto:mmartin5@austin.rr.com">Mike Martin</a>
31  * @version $Revision: 1.7 $
32  */

33
34 public abstract class StorageTestCase extends PersistenceTestCase
35 {
36     private static final Category LOG = Category.getInstance(StorageTestCase.class);
37
38     protected static final int TEST_OBJECT_COUNT = 50;
39
40     protected Object JavaDoc[] ids = new Object JavaDoc[TEST_OBJECT_COUNT];
41     protected TestObject[] objs = new TestObject[TEST_OBJECT_COUNT];
42
43
44     /**
45      * Used by the JUnit framework to construct tests. Normally, programmers
46      * would never explicitly use this constructor.
47      *
48      * @param name Name of the <tt>TestCase</tt>.
49      */

50
51     public StorageTestCase(String JavaDoc name)
52     {
53         super(name);
54     }
55
56
57     protected void runStorageTestFor(Class JavaDoc c) throws Exception JavaDoc
58     {
59         insertObjects(c);
60         validateObjects(c);
61         updateObjects(c);
62         validateObjects(c);
63         iterateUsingExtent(c);
64         validateTransactionalRefresh(c);
65         removeObjects();
66         validateNewObjectRollback(c);
67         validateTransientTransactional(c);
68     }
69
70
71     /**
72      * Asserts that the persistent fields of two test objects are equal using
73      * the <tt>compareTo()</tt> method. The <tt>equals()</tt> method cannot be
74      * used for this purpose because, for most persistence-capable objects
75      * (including all our test widgets), it only compares JDO identity.
76      *
77      * @param expected An object having the expected field values.
78      * @param actual The object to compare fields against.
79      *
80      * @see TestObject#compareTo
81      */

82
83     protected void assertFieldsEqual(TestObject expected, TestObject actual)
84     {
85         assertTrue("Incorrect field values in object, was " + actual + ", should be " + expected, actual.compareTo(expected));
86     }
87
88
89     protected void assertResultsEqual(Set JavaDoc expected, Collection JavaDoc results)
90     {
91         assertTrue("Query has no expected results (test is broken)", !expected.isEmpty());
92         assertTrue("Query returned no rows", !results.isEmpty());
93
94         HashSet JavaDoc actual = new HashSet JavaDoc(results);
95
96         assertEquals("Query returned duplicate rows", results.size(), actual.size());
97         assertEquals("Query did not return expected results", expected, actual);
98     }
99
100
101     protected void insertObjects(Class JavaDoc c) throws Exception JavaDoc
102     {
103         /*
104          * Insert TEST_OBJECT_COUNT random objects.
105          */

106
107         LOG.info("Inserting " + TEST_OBJECT_COUNT + " " + c.getName() + " objects");
108         PersistenceManager pm = pmf.getPersistenceManager();
109         Transaction tx = pm.currentTransaction();
110
111         try
112         {
113             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
114             {
115                 tx.begin();
116
117                 TestObject obj = (TestObject)c.newInstance();
118                 obj.fillRandom();
119
120                 objs[i] = (TestObject)obj.clone();
121
122                 assertFieldsEqual(obj, objs[i]);
123
124                 pm.makePersistent(obj);
125
126                 ids[i] = JDOHelper.getObjectId(obj);
127
128                 tx.commit();
129             }
130         }
131         finally
132         {
133             if (tx.isActive())
134                 tx.rollback();
135
136             pm.close();
137         }
138     }
139
140
141     protected void validateObjects(Class JavaDoc c) throws Exception JavaDoc
142     {
143         /*
144          * Read them back and verify that they contain what they should.
145          */

146
147         LOG.info("Validating " + TEST_OBJECT_COUNT + " " + c.getName() + " objects:");
148         LOG.info(" Normal read");
149         PersistenceManager pm = pmf.getPersistenceManager();
150         Transaction tx = pm.currentTransaction();
151
152         try
153         {
154             TestObject[] loaded = new TestObject[TEST_OBJECT_COUNT];
155
156             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
157             {
158                 tx.begin();
159
160                 TestObject obj = (TestObject)pm.getObjectById(ids[i], true);
161
162                 assertFieldsEqual(objs[i], obj);
163
164                 loaded[i] = obj;
165
166                 tx.commit();
167             }
168         }
169         finally
170         {
171             if (tx.isActive())
172                 tx.rollback();
173
174             pm.close();
175         }
176
177
178         /*
179          * Read some of them back and verify them using non-transactional reads.
180          * Only some are done because non-transactional reads are much slower
181          * unless connection pooling is used (eventually we should use pooling
182          * when testing).
183          */

184
185         LOG.info(" Non-transactional read");
186         pm = pmf.getPersistenceManager();
187         tx = pm.currentTransaction();
188
189         try
190         {
191             tx.setNontransactionalRead(true);
192
193             for (int i = 0; i < TEST_OBJECT_COUNT; i += 10)
194             {
195                 TestObject obj = (TestObject)pm.getObjectById(ids[i], false);
196
197                 assertFieldsEqual(objs[i], obj);
198             }
199         }
200         finally
201         {
202             pm.close();
203         }
204
205         /*
206          * Read some of them back, verify them, then verify values get retained
207          * after commit when retainValues mode is on.
208          */

209
210         LOG.info(" Retain values mode");
211         pm = pmf.getPersistenceManager();
212         tx = pm.currentTransaction();
213
214         try
215         {
216             tx.setRetainValues(true);
217             tx.begin();
218
219             TestObject[] loaded = new TestObject[TEST_OBJECT_COUNT];
220
221             for (int i = 0; i < TEST_OBJECT_COUNT; i += 10)
222             {
223                 TestObject obj = (TestObject)pm.getObjectById(ids[i], true);
224
225                 assertFieldsEqual(objs[i], obj);
226
227                 loaded[i] = obj;
228             }
229
230             tx.commit();
231
232             for (int i = 0; i < TEST_OBJECT_COUNT; i += 10)
233                 assertFieldsEqual(objs[i], loaded[i]);
234         }
235         finally
236         {
237             if (tx.isActive())
238                 tx.rollback();
239
240             pm.close();
241         }
242     }
243
244
245     protected void updateObjects(Class JavaDoc c) throws Exception JavaDoc
246     {
247         /*
248          * Update them all with new values.
249          */

250
251         LOG.info("Updating " + TEST_OBJECT_COUNT + " " + c.getName() + " objects");
252         PersistenceManager pm = pmf.getPersistenceManager();
253         Transaction tx = pm.currentTransaction();
254
255         try
256         {
257             /*
258              * Test basic update functionality by filling each object with new
259              * random data.
260              */

261             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
262             {
263                 tx.begin();
264
265                 TestObject obj = (TestObject)pm.getObjectById(ids[i], false);
266                 obj.fillRandom();
267
268                 objs[i] = (TestObject)obj.clone();
269
270                 assertFieldsEqual(obj, objs[i]);
271
272                 tx.commit();
273             }
274
275             if (Widget.class.isAssignableFrom(c))
276             {
277                 /*
278                  * Test updates where we write a default-fetch-group field
279                  * before the default fetch group has been loaded.
280                  * validateObjects() will ensure that the update does not get
281                  * lost.
282                  */

283                 for (int i = 0; i < TEST_OBJECT_COUNT; i += 10)
284                 {
285                     tx.begin();
286
287                     Widget w = (Widget)pm.getObjectById(ids[i], false);
288                     byte b = w.setByteFieldRandom();
289                     ((Widget)objs[i]).setByteField(b);
290
291                     tx.commit();
292                 }
293             }
294         }
295         finally
296         {
297             if (tx.isActive())
298                 tx.rollback();
299
300             pm.close();
301         }
302     }
303
304
305     protected void iterateUsingExtent(Class JavaDoc c) throws Exception JavaDoc
306     {
307         /*
308          * Iterate over them using an Extent and verify that they're all
309          * returned.
310          */

311
312         LOG.info("Iterating over " + TEST_OBJECT_COUNT + " " + c.getName() + " objects with an Extent");
313         PersistenceManager pm = pmf.getPersistenceManager();
314         Transaction tx = pm.currentTransaction();
315
316         try
317         {
318             tx.begin();
319
320             Extent extent = pm.getExtent(c, true);
321             Iterator JavaDoc ei = extent.iterator();
322
323             try
324             {
325                 HashSet JavaDoc returned = new HashSet JavaDoc();
326
327                 while (ei.hasNext())
328                 {
329                     TestObject obj = (TestObject)ei.next();
330
331                     assertTrue("Object returned twice from Extent iterator: " + obj, returned.add(obj));
332                 }
333
334                 assertEquals(TEST_OBJECT_COUNT, returned.size());
335
336                 for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
337                 {
338                     TestObject obj = (TestObject)pm.getObjectById(ids[i], true);
339
340                     assertTrue("Object never returned from Extent iterator: " + obj, returned.remove(obj));
341                 }
342             }
343             finally
344             {
345                 extent.close(ei);
346             }
347
348             tx.commit();
349         }
350         finally
351         {
352             if (tx.isActive())
353                 tx.rollback();
354
355             pm.close();
356         }
357     }
358
359
360     protected void validateTransactionalRefresh(Class JavaDoc c) throws Exception JavaDoc
361     {
362         /*
363          * Validate that persistent non-transactional objects transition to
364          * persistent, and refresh themselves, when accessed from within a
365          * transaction.
366          */

367
368         LOG.info("Validating transactional refresh on " + TEST_OBJECT_COUNT + " " + c.getName() + " objects");
369         PersistenceManager pm1 = pmf.getPersistenceManager();
370         Transaction tx1 = pm1.currentTransaction();
371         tx1.setRetainValues(true);
372
373         try
374         {
375             PersistenceManager pm2 = pmf.getPersistenceManager();
376             Transaction tx2 = pm2.currentTransaction();
377
378             Random JavaDoc rnd = new Random JavaDoc(0);
379             TestObject[] pobjs = new TestObject[TEST_OBJECT_COUNT];
380             
381             try
382             {
383                 /* Load all of the objects using pm1. */
384                 tx1.begin();
385
386                 for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
387                 {
388                     /* Half will be Hollow and half PersistentClean. */
389                     boolean validate = rnd.nextBoolean();
390
391                     pobjs[i] = (TestObject)pm1.getObjectById(ids[i], validate);
392
393                     /* Half of the PersistentClean will be fully loaded. */
394                     if (validate && rnd.nextBoolean())
395                         assertFieldsEqual(objs[i], pobjs[i]);
396                 }
397
398                 tx1.commit();
399
400                 for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
401                 {
402                     assertTrue("Object is not persistent: " + ids[i], JDOHelper.isPersistent(pobjs[i]));
403                     assertTrue("Object is transactional: " + ids[i], !JDOHelper.isTransactional(pobjs[i]));
404                 }
405
406                 /* Modify them all using pm2. */
407                 tx2.begin();
408
409                 for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
410                 {
411                     TestObject obj = (TestObject)pm2.getObjectById(ids[i], false);
412                     obj.fillRandom();
413
414                     objs[i] = (TestObject)obj.clone();
415
416                     assertFieldsEqual(obj, objs[i]);
417                 }
418
419                 tx2.commit();
420
421                 /* Access them all inside a transaction using pm1. */
422                 tx1.begin();
423
424                 for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
425                 {
426                     assertTrue("Object is not persistent: " + ids[i], JDOHelper.isPersistent(pobjs[i]));
427                     assertTrue("Object is transactional: " + ids[i], !JDOHelper.isTransactional(pobjs[i]));
428
429                     assertFieldsEqual(objs[i], pobjs[i]);
430
431                     assertTrue("Object is not persistent: " + ids[i], JDOHelper.isPersistent(pobjs[i]));
432                     assertTrue("Object is not transactional: " + ids[i], JDOHelper.isTransactional(pobjs[i]));
433                 }
434
435                 tx1.commit();
436             }
437             finally
438             {
439                 if (tx2.isActive())
440                     tx2.rollback();
441
442                 pm2.close();
443             }
444         }
445         finally
446         {
447             if (tx1.isActive())
448                 tx1.rollback();
449
450             pm1.close();
451         }
452     }
453
454
455     protected void removeObjects() throws Exception JavaDoc
456     {
457         /*
458          * Remove all of the objects.
459          */

460
461         LOG.info("Removing " + TEST_OBJECT_COUNT + " objects");
462         PersistenceManager pm = pmf.getPersistenceManager();
463         Transaction tx = pm.currentTransaction();
464
465         try
466         {
467             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
468             {
469                 tx.begin();
470
471                 TestObject obj = (TestObject)pm.getObjectById(ids[i], false);
472
473                 pm.deletePersistent(obj);
474
475                 tx.commit();
476             }
477         }
478         finally
479         {
480             if (tx.isActive())
481                 tx.rollback();
482
483             pm.close();
484         }
485     }
486
487
488     protected void validateNewObjectRollback(Class JavaDoc c) throws Exception JavaDoc
489     {
490         /*
491          * Create TEST_OBJECT_COUNT random objects, update them, rollback the
492          * transaction, and verify they return to being transient objects
493          * having their former values. Requires RestoreValues == true in order
494          * to get the restoration on rollback.
495          */

496
497         LOG.info("Testing rollback of updates on " + TEST_OBJECT_COUNT + " new " + c.getName() + " objects");
498         PersistenceManager pm = pmf.getPersistenceManager();
499         Transaction tx = pm.currentTransaction();
500         tx.setRestoreValues(true);
501
502         try
503         {
504             TestObject[] pobjs = new TestObject[TEST_OBJECT_COUNT];
505
506             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
507             {
508                 objs[i] = (TestObject)c.newInstance();
509                 objs[i].fillRandom();
510
511                 pobjs[i] = (TestObject)objs[i].clone();
512             }
513
514             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
515             {
516                 tx.begin();
517
518                 pm.makePersistent(pobjs[i]);
519
520                 pobjs[i].fillRandom();
521
522                 tx.rollback();
523             }
524
525             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
526             {
527                 assertNull(JDOHelper.getPersistenceManager(pobjs[i]));
528                 assertFieldsEqual(objs[i], pobjs[i]);
529             }
530         }
531         finally
532         {
533             if (tx.isActive())
534                 tx.rollback();
535
536             pm.close();
537         }
538     }
539
540
541     protected void validateTransientTransactional(Class JavaDoc c) throws Exception JavaDoc
542     {
543         /*
544          * Create TEST_OBJECT_COUNT random objects, make them TransientClean,
545          * update them, rollback the transaction, and verify they return to
546          * being TransientClean objects having their former values. Requires
547          * RestoreValues == true in order to get the restoration on rollback.
548          */

549
550         LOG.info("Testing rollback of updates on " + TEST_OBJECT_COUNT + " transient transactional " + c.getName() + " objects");
551         PersistenceManager pm = pmf.getPersistenceManager();
552         Transaction tx = pm.currentTransaction();
553         tx.setRestoreValues(true);
554
555         try
556         {
557             TestObject[] pobjs = new TestObject[TEST_OBJECT_COUNT];
558
559             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
560             {
561                 objs[i] = (TestObject)c.newInstance();
562                 objs[i].fillRandom();
563
564                 pobjs[i] = (TestObject)objs[i].clone();
565             }
566
567             tx.begin();
568
569             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
570             {
571                 TestObject obj = pobjs[i];
572
573                 assertFalse("Object should not be transactional: " + obj, JDOHelper.isTransactional(obj));
574                 assertFalse("Object should not be dirty: " + obj, JDOHelper.isDirty(obj));
575
576                 pm.makeTransactional(obj);
577
578                 assertTrue("Object should be transactional: " + obj, JDOHelper.isTransactional(obj));
579                 assertFalse("Object should not be dirty: " + obj, JDOHelper.isDirty(obj));
580
581                 obj.fillRandom();
582
583                 assertTrue("Object should be dirty: " + obj, JDOHelper.isDirty(obj));
584             }
585
586             tx.rollback();
587
588             for (int i = 0; i < TEST_OBJECT_COUNT; ++i)
589             {
590                 TestObject obj = pobjs[i];
591
592                 assertTrue("Object should be transactional: " + obj, JDOHelper.isTransactional(obj));
593                 assertFalse("Object should not be dirty: " + obj, JDOHelper.isDirty(obj));
594                 assertFieldsEqual(objs[i], obj);
595
596                 pm.makeNontransactional(obj);
597
598                 assertNull("Object should have transitioned to an unmanaged transient", JDOHelper.getPersistenceManager(obj));
599             }
600         }
601         finally
602         {
603             if (tx.isActive())
604                 tx.rollback();
605
606             pm.close();
607         }
608     }
609 }
610
Popular Tags