Thank you, Michael!  I will check in the patch.

-- Michelle

Michael Watzek wrote:

Hi,

attached you find the patch for JDO-48.

In addition to the life cycle tests and class JDO_Test, I changed class
PersistenceManagerTest. There I removed methods tearDown(),
cleanupMylib(), and cleanupCompany(). I added method localTearDown()
which adds tear down classes, and I moved method
getAllObjects(PersistenceManager, Class) to class JDO_Test.

Furthermore, I changed a few tests in .../jdo/tck/extents because these
tests called cleanup() in methods testXXX. I removed those calls and
added methods localSetUp() adding tear down classes.

Also, the patch includes the changes to JDO_Test.runBare() which I have suggested in a previous mail.

You find the change log of my workspace below.

Regards,
Michael

M
test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java
M
test/java/org/apache/jdo/tck/lifecycle/MultiplePMsReturnInstancesRepresentingSamePC.java
M
test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateCommit.java
M
test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateRollback.java M test/java/org/apache/jdo/tck/lifecycle/HollowInstanceMaintainsPK.java
M
test/java/org/apache/jdo/tck/lifecycle/PMsCanSharePCClassesButNotPCInstances.java
M      test/java/org/apache/jdo/tck/lifecycle/StateTransitions.java
M
test/java/org/apache/jdo/tck/lifecycle/PMReturnsIdenticalInstancesForEqualObjIds.java
M
test/java/org/apache/jdo/tck/api/persistencemanager/PersistenceManagerTest.java
M
test/java/org/apache/jdo/tck/api/persistencemanager/getobject/GetObjectByIdNoValidationInstanceNotInDatastore.jav
a
M
test/java/org/apache/jdo/tck/extents/IteratorHasNextFalseAfterExtentClose.java
M
test/java/org/apache/jdo/tck/extents/InstancesPersistedPriorToIterationReturned.java
M
test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentCloseAll.java
M      test/java/org/apache/jdo/tck/extents/IteratorMutatingMethods.java
M
test/java/org/apache/jdo/tck/extents/InstancesDeletedPriorToIterationNotReturned.java
M
test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentClose.java
M      test/java/org/apache/jdo/tck/extents/CloseAll.java
M      test/java/org/apache/jdo/tck/JDO_Test.java

------------------------------------------------------------------------

Index: 
test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java
===================================================================
--- 
test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java
 (revision 178413)
+++ 
test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java
 (working copy)
@@ -19,8 +19,6 @@
import java.util.Iterator;

import javax.jdo.Extent;
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Transaction;

import org.apache.jdo.tck.JDO_Test;
@@ -47,6 +45,9 @@
                
        private static final int NUM_OBJECTS = 50;

+    /** The persistent instances of this test. */
+    private Object[] obj;
+ /**
     * The <code>main</code> is called when the class
     * is directly executed from the command line.
@@ -56,15 +57,16 @@
                
BatchTestRunner.run(ObjectIdNotModifiedWhenObjectIdInstanceModified.class);
    }

-    public ObjectIdNotModifiedWhenObjectIdInstanceModified()
-    {
+    /**
+     * @see JDO_Test#localSetUp()
+     */
+    protected void localSetUp() {
+        pm = getPM();
+        addTearDownClass(StateTransitionObj.class);
+        obj = generatePersistentInstances();
    }
-
+ public void test() throws Exception {
-               pm = getPM();
-               
-               Object[] obj = generatePersistentInstances();
-
                Extent extent = pm.getExtent(StateTransitionObj.class, false);
                Iterator iter = extent.iterator();
                if( !iter.hasNext() ){
Index: 
test/java/org/apache/jdo/tck/lifecycle/MultiplePMsReturnInstancesRepresentingSamePC.java
===================================================================
--- 
test/java/org/apache/jdo/tck/lifecycle/MultiplePMsReturnInstancesRepresentingSamePC.java
    (revision 178413)
+++ 
test/java/org/apache/jdo/tck/lifecycle/MultiplePMsReturnInstancesRepresentingSamePC.java
    (working copy)
@@ -20,7 +20,6 @@

import javax.jdo.Extent;
import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Transaction;

import org.apache.jdo.tck.JDO_Test;
@@ -49,6 +48,9 @@

        private static final int NUM_OBJECTS = 50;

+    /** The persistent instances of this test. */
+    private Object[] obj;
+ /**
     * The <code>main</code> is called when the class
     * is directly executed from the command line.
@@ -58,22 +60,24 @@
                
BatchTestRunner.run(MultiplePMsReturnInstancesRepresentingSamePC.class);
    }

-    public MultiplePMsReturnInstancesRepresentingSamePC()
-    {
+    /**
+     * @see JDO_Test#localSetUp()
+     */
+    protected void localSetUp() {
+        pm = getPM();
+        addTearDownClass(StateTransitionObj.class);
+        obj = generatePersistentInstances();
    }
-
+ public void test() {
                PersistenceManager pm2 = null;
                PersistenceManager pm3 = null;
        
            try {
-                       pm = getPM();
                        // Get two more PMs
                        pm2 = pmf.getPersistenceManager();
                        pm3 = pmf.getPersistenceManager();

-                       Object[] obj = generatePersistentInstances();
-
                        Extent extent = pm.getExtent(StateTransitionObj.class, 
false);
                        Iterator iter = extent.iterator();
                        if( !iter.hasNext() ){
Index: 
test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateCommit.java
===================================================================
--- 
test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateCommit.java   
    (revision 178413)
+++ 
test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateCommit.java   
    (working copy)
@@ -16,13 +16,6 @@
package org.apache.jdo.tck.lifecycle;

-import java.util.Iterator;
-
-import javax.jdo.Extent;
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
-import javax.jdo.Transaction;
-
import org.apache.jdo.tck.JDO_Test;
import org.apache.jdo.tck.pc.lifecycle.StateTransitionObj;
import org.apache.jdo.tck.util.BatchTestRunner;
Index: 
test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateRollback.java
===================================================================
--- 
test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateRollback.java 
    (revision 178413)
+++ 
test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateRollback.java 
    (working copy)
@@ -16,11 +16,6 @@
package org.apache.jdo.tck.lifecycle;

-import java.util.Iterator;
-
-import javax.jdo.Extent;
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Transaction;

import org.apache.jdo.tck.JDO_Test;
Index: test/java/org/apache/jdo/tck/lifecycle/HollowInstanceMaintainsPK.java
===================================================================
--- test/java/org/apache/jdo/tck/lifecycle/HollowInstanceMaintainsPK.java       
(revision 178413)
+++ test/java/org/apache/jdo/tck/lifecycle/HollowInstanceMaintainsPK.java       
(working copy)
@@ -16,16 +16,9 @@
package org.apache.jdo.tck.lifecycle;

-import java.util.Iterator;
-
-import javax.jdo.Extent;
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
-import javax.jdo.Transaction;
-
import org.apache.jdo.tck.JDO_Test;
-import org.apache.jdo.tck.pc.mylib.PCRect;
import org.apache.jdo.tck.pc.mylib.PCPoint;
+import org.apache.jdo.tck.pc.mylib.PCRect;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
@@ -64,7 +57,6 @@
            pm.currentTransaction().begin();

            PCRect obj = getPersistentNewInstance();
-
            long beforeValue=obj.getId();
            pm.currentTransaction().commit(); // obj should transition to HOLLOW
            long afterValue=obj.getId();
@@ -87,6 +79,8 @@
                 "from transient instance via makePersistent(), state is " +
                 states[curr]);
        }
+        addTearDownInstance(obj);
        return obj;
    }
+
}
Index: 
test/java/org/apache/jdo/tck/lifecycle/PMsCanSharePCClassesButNotPCInstances.java
===================================================================
--- 
test/java/org/apache/jdo/tck/lifecycle/PMsCanSharePCClassesButNotPCInstances.java
   (revision 178413)
+++ 
test/java/org/apache/jdo/tck/lifecycle/PMsCanSharePCClassesButNotPCInstances.java
   (working copy)
@@ -67,10 +67,13 @@
        BatchTestRunner.run(PMsCanSharePCClassesButNotPCInstances.class);
    }

-    public PMsCanSharePCClassesButNotPCInstances()
-    {
+    /**
+     * @see JDO_Test#localSetUp()
+     */
+    protected void localSetUp() {
+        addTearDownClass(StateTransitionObj.class);
    }
-
+ public void test() {
        // test shared PC - only one PM should succeed to insert the shared PC
        threads = 0;
@@ -105,11 +108,11 @@
            t.start();
        }
- Thread.currentThread().yield();
+        Thread.yield();
while (! attemptsComplete()) { try {
-                Thread.currentThread().sleep(100);
+                Thread.sleep(100);
            } catch (InterruptedException ex) {
                logger.debug("interrupted while waiting for threads to insert");
            }
@@ -117,7 +120,7 @@

        while (threads > 0) {
            try {
-                Thread.currentThread().sleep(100);
+                Thread.sleep(100);
            } catch (InterruptedException ex) {
                logger.debug("interrupted while waiting for threads to finish");
            }
@@ -180,7 +183,7 @@

                while (!attemptsComplete()) {
                    try {
-                        Thread.currentThread().sleep(100);
+                        Thread.sleep(100);
                    } catch (InterruptedException ex) {
                        if (debug) logger.debug(" interrupted");
                    }
Index: test/java/org/apache/jdo/tck/lifecycle/StateTransitions.java
===================================================================
--- test/java/org/apache/jdo/tck/lifecycle/StateTransitions.java        
(revision 178413)
+++ test/java/org/apache/jdo/tck/lifecycle/StateTransitions.java        
(working copy)
@@ -19,8 +19,6 @@
import java.util.Iterator;

import javax.jdo.Extent;
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Transaction;

import org.apache.jdo.tck.JDO_Test;
@@ -230,14 +228,16 @@
        {   true,          false,       false }   // retrieve with active 
datastore transaction
    };

-    public StateTransitions()
-    {
+    /**
+     * @see JDO_Test#localSetUp()
+     */
+    protected void localSetUp() {
+        pm = getPM();
+        generatePersistentInstances();
+        addTearDownClass(StateTransitionObj.class);
    }
-
+ public void test() {
-        pm = getPM();
-        generatePersistentInstances();
-
        scenario = DATASTORE_TX;
        checkTransitions();

Index: 
test/java/org/apache/jdo/tck/lifecycle/PMReturnsIdenticalInstancesForEqualObjIds.java
===================================================================
--- 
test/java/org/apache/jdo/tck/lifecycle/PMReturnsIdenticalInstancesForEqualObjIds.java
       (revision 178413)
+++ 
test/java/org/apache/jdo/tck/lifecycle/PMReturnsIdenticalInstancesForEqualObjIds.java
       (working copy)
@@ -19,8 +19,6 @@
import java.util.Iterator;

import javax.jdo.Extent;
-import javax.jdo.PersistenceManager;
-import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Transaction;

import org.apache.jdo.tck.JDO_Test;
@@ -47,6 +45,9 @@
private static final int NUM_OBJECTS = 50;

+    /** The persistent instances of this test. */
+    private Object[] obj;
+ /**
     * The <code>main</code> is called when the class
     * is directly executed from the command line.
@@ -56,15 +57,16 @@
                
BatchTestRunner.run(PMReturnsIdenticalInstancesForEqualObjIds.class);
    }

-    public PMReturnsIdenticalInstancesForEqualObjIds()
-    {
+    /**
+     * @see JDO_Test#localSetUp()
+     */
+    protected void localSetUp() {
+        pm = getPM();
+        addTearDownClass(StateTransitionObj.class);
+        obj = generatePersistentInstances();
    }
-
+ public void test() {
-           pm = getPM();
-
-           Object[] obj = generatePersistentInstances();
-
        Extent extent = pm.getExtent(StateTransitionObj.class, false);
        Iterator iter = extent.iterator();
        if( !iter.hasNext() ){
Index: 
test/java/org/apache/jdo/tck/api/persistencemanager/PersistenceManagerTest.java
===================================================================
--- 
test/java/org/apache/jdo/tck/api/persistencemanager/PersistenceManagerTest.java 
    (revision 178413)
+++ 
test/java/org/apache/jdo/tck/api/persistencemanager/PersistenceManagerTest.java 
    (working copy)
@@ -17,11 +17,7 @@
package org.apache.jdo.tck.api.persistencemanager;


-import java.util.Collection;
-import java.util.Vector;
-
import javax.jdo.PersistenceManager;
-import javax.jdo.Query;
import javax.jdo.Transaction;

import org.apache.jdo.tck.JDO_Test;
@@ -36,76 +32,19 @@
    /** */
    protected PersistenceManagerTest() { }

-    /** */
-    protected void tearDown() {
-        Throwable cleanupFailure = null;
-        try {
-            cleanup();
-            cleanupMylib();
-            cleanupCompany();
-        }
-        catch (Throwable ex) {
-            cleanupFailure = ex;
-            // set testSucceeded to false, otherwise a failure during
-            // super.tearDown would swallow this exception
-            testSucceeded = false;
-        }
-
-        // cleanup pmf
-        super.tearDown();
-
-        // fail if there was an exception during cleanup
-        if (cleanupFailure != null) {
-            fail("Exception during cleanupMylib: " + cleanupFailure);
-        }
+ /** + * @see JDO_Test#localSetUp()
+     */
+    protected void localSetUp() {
+        // The order of addTearDownClass calls is significant
+        // as it takes into account database FKs.
+        addTearDownClass(PCRect.class);
+        addTearDownClass(PCPoint.class);
+        addTearDownClass(Department.class);
+        addTearDownClass(Company.class);
    }
/** */
-    protected void cleanupMylib() {
-        PersistenceManager pm = getPM();
-        Transaction tx = null;
-        try {
-            pm = pmf.getPersistenceManager();
-            tx = pm.currentTransaction();
-            tx.begin();
-            // Note, remove PCRect instances first because of FK constraints
-            Collection c = getAllObjects(pm, PCRect.class);
-            pm.deletePersistentAll(c);
-            c = getAllObjects(pm, PCPoint.class);
-            pm.deletePersistentAll(c);
-            tx.commit();
-        }
-        finally {
-            if ((tx != null) && tx.isActive())
-                tx.rollback();
-            if ((pm != null) && pm.isClosed())
-                pm.close();
-        }
-  }
-
-     /** */
-    protected void cleanupCompany() {
-        PersistenceManager pm = getPM();
-        Transaction tx = null;
-        try {
-            pm = pmf.getPersistenceManager();
-            tx = pm.currentTransaction();
-            tx.begin();
-            Collection c = getAllObjects(pm, Department.class);
-            pm.deletePersistentAll(c);
-            c = getAllObjects(pm, Company.class);
-            pm.deletePersistentAll(c);
-            tx.commit();
-        }
-        finally {
-            if ((tx != null) && tx.isActive())
-                tx.rollback();
-            if ((pm != null) && pm.isClosed())
-                pm.close();
-        }
-    }
- - /** */
    protected Object createPCPointInstance(PersistenceManager pm) {
        PCPoint p1 = new PCPoint(8,8);
        Transaction tx = pm.currentTransaction();
@@ -113,6 +52,7 @@
        pm.makePersistent(p1);
        Object oid = pm.getObjectId(p1);
        tx.commit();
+        addTearDownInstance(p1);
        return oid;
    }
@@ -126,21 +66,6 @@
    }

    /** */
-    protected Collection getAllObjects(PersistenceManager pm, Class pcClass) {
-        Collection col = new Vector() ;
-        try {
-            Query query = pm.newQuery();
-            query.setClass(pcClass);
-            query.setCandidates(pm.getExtent(pcClass, false));
-            Object result = query.execute();
-            col = (Collection)result;
-        } catch (Exception e) {
-            fail("Exception in getAllObjects()" + e);
-        }
-        return col ;
-    }
-
-    /** */
    public boolean testState(PCPoint obj, int expectState, String str) {
        int actualState = currentState(obj);
        if (actualState != expectState) {
Index: 
test/java/org/apache/jdo/tck/api/persistencemanager/getobject/GetObjectByIdNoValidationInstanceNotInDatastore.java
===================================================================
--- 
test/java/org/apache/jdo/tck/api/persistencemanager/getobject/GetObjectByIdNoValidationInstanceNotInDatastore.java
  (revision 178413)
+++ 
test/java/org/apache/jdo/tck/api/persistencemanager/getobject/GetObjectByIdNoValidationInstanceNotInDatastore.java
  (working copy)
@@ -76,7 +76,6 @@
        catch (JDOObjectNotFoundException ex) {
            // expected exception
        }
-        cleanup();
        if (debug)
            logger.debug ("END 
GetObjectByIdNoValidationInstanceNotInDatastore");
   }
Index: 
test/java/org/apache/jdo/tck/extents/IteratorHasNextFalseAfterExtentClose.java
===================================================================
--- 
test/java/org/apache/jdo/tck/extents/IteratorHasNextFalseAfterExtentClose.java  
    (revision 178413)
+++ 
test/java/org/apache/jdo/tck/extents/IteratorHasNextFalseAfterExtentClose.java  
    (working copy)
@@ -91,7 +91,6 @@
            }
} finally {
-            cleanup();
        }
    }
}
Index: 
test/java/org/apache/jdo/tck/extents/InstancesPersistedPriorToIterationReturned.java
===================================================================
--- 
test/java/org/apache/jdo/tck/extents/InstancesPersistedPriorToIterationReturned.java
        (revision 178413)
+++ 
test/java/org/apache/jdo/tck/extents/InstancesPersistedPriorToIterationReturned.java
        (working copy)
@@ -78,7 +78,6 @@
            }
} finally {
-            cleanup();
        }
    }
}
Index: test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentCloseAll.java
===================================================================
--- test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentCloseAll.java   
(revision 178413)
+++ test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentCloseAll.java   
(working copy)
@@ -83,7 +83,6 @@
} finally {
            rollbackTransaction();
-            cleanup();
        }
    }
Index: test/java/org/apache/jdo/tck/extents/IteratorMutatingMethods.java
===================================================================
--- test/java/org/apache/jdo/tck/extents/IteratorMutatingMethods.java   
(revision 178413)
+++ test/java/org/apache/jdo/tck/extents/IteratorMutatingMethods.java   
(working copy)
@@ -67,7 +67,6 @@
            if (debug) logger.debug("expected exception " + ex);
} finally {
-            cleanup();
        }
    }
}
Index: 
test/java/org/apache/jdo/tck/extents/InstancesDeletedPriorToIterationNotReturned.java
===================================================================
--- 
test/java/org/apache/jdo/tck/extents/InstancesDeletedPriorToIterationNotReturned.java
       (revision 178413)
+++ 
test/java/org/apache/jdo/tck/extents/InstancesDeletedPriorToIterationNotReturned.java
       (working copy)
@@ -78,7 +78,6 @@
            }
} finally {
-            cleanup();
        }
    }
}
Index: test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentClose.java
===================================================================
--- test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentClose.java      
(revision 178413)
+++ test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentClose.java      
(working copy)
@@ -85,7 +85,6 @@
} catch (Exception unexpected) {
                rollbackTransaction();
-                cleanup();
                fail(ASSERTION_FAILED,
                     "unexpected exception " + unexpected);
            }
@@ -94,9 +93,6 @@
            fail(ASSERTION_FAILED,
                 "unexpected exception " + unexpected);
} - finally {
-            cleanup();
-        }
    }

    /** */
Index: test/java/org/apache/jdo/tck/extents/CloseAll.java
===================================================================
--- test/java/org/apache/jdo/tck/extents/CloseAll.java  (revision 178413)
+++ test/java/org/apache/jdo/tck/extents/CloseAll.java  (working copy)
@@ -79,7 +79,6 @@
} finally {
            rollbackTransaction();
-            cleanup();
        }
    }
}
Index: test/java/org/apache/jdo/tck/JDO_Test.java
===================================================================
--- test/java/org/apache/jdo/tck/JDO_Test.java  (revision 178413)
+++ test/java/org/apache/jdo/tck/JDO_Test.java  (working copy)
@@ -21,14 +21,21 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
-import java.lang.Runtime;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Properties;
+import java.util.Vector;

+import javax.jdo.JDOException;
+import javax.jdo.JDOFatalException;
import javax.jdo.JDOHelper;
+import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.PersistenceManagerFactory;
-import javax.jdo.JDOException;
+import javax.jdo.Query;

+import junit.framework.AssertionFailedError;
import junit.framework.TestCase;

import org.apache.commons.logging.Log;
@@ -128,6 +135,24 @@
    /** true if debug logging in enabled. */
    protected boolean debug = logger.isDebugEnabled();
+ /** + * Indicates an exception thrown in method <code>tearDown</code>. + * At the end of method <code>tearDown</code> this field is nullified. + */
+    private Throwable tearDownThrowable;
+ + /** + * A list of registered oid instances. + * Corresponding pc instances are deleted in <code>localTearDown</code>.
+     */
+    private Collection oids = new LinkedList();
+ + /** + * A list of registered pc classes. + * Th extents of these classes are deleted in <code>localTearDown</code>.
+     */
+    private Collection pcClasses = new LinkedList();
+ /** */
    protected JDO_Test() {
        PMFProperties = System.getProperty("PMFProperties");
@@ -136,49 +161,187 @@
    /** */
    protected void setUp() throws Exception {
        pmf = getPMF();
+        localSetUp();
    }
/**
+     * Subclasses may override this method to allocate any data and resources
+     * that they need in order to successfully execute this testcase.
+     */
+    protected void localSetUp() {}
+ + /**
     * Runs the bare test sequence.
     * @exception Throwable if any exception is thrown
     */
    public void runBare() throws Throwable {
-        setUp();
        try {
            testSucceeded = false;
+            setUp();
            runTest();
            testSucceeded = true;
        }
+        catch (AssertionFailedError e) {
+            logger.error("Exception during setUp or runtest: ", e);
+            throw e;
+        }
+        catch (Throwable t) {
+            logger.fatal("Exception during setUp or runtest: ", t);
+            throw t;
+        }
        finally {
            tearDown();
-            long freeMem = Runtime.getRuntime().freeMemory();
-            if (debug) logger.debug("Free memory: " + freeMem);
+            if (debug) {
+                logger.debug("Free memory: " + 
Runtime.getRuntime().freeMemory());
+            }
        }
    }

-    /** */
+    /**
+     * Sets field <code>tearDownThrowable</code> if it is <code>null</code>.
+ * Else, the given throwable is logged using fatal log level. + * @param throwable the throwable
+     */
+    private void setTearDownThrowable(String context, Throwable throwable)
+    {
+        logger.fatal("Exception during "+context+": ", throwable);
+        if (this.tearDownThrowable == null) {
+            this.tearDownThrowable = throwable;
+        }
+    }
+ + /**
+     * This method clears data and resources allocated by testcases.
+     * It first closes the persistence manager of this testcase.
+ * Then it calls method <code>localTearDown</code>. + * Subclasses may override that method to clear any data and resources
+     * that they have allocated in method <code>localSetUp</code>.
+     * Finally, this method closes the persistence manager factory.<p>
+ * + * <b>Note:</b>These methods are called always, regardless of any exceptions. + * The first caught exception is kept in field <code>tearDownThrowable</code>. + * That exception is thrown as a nested exception of <code>JDOFatalException</code>
+     * if and only if the testcase executed successful.
+     * Otherwise that exception is logged using fatal log level.
+     * All other exceptions are logged using fatal log level, always.
+     */
    protected void tearDown() {
        try {
-            cleanup();
+            cleanupPM();
+ } + catch (Throwable t) {
+            setTearDownThrowable("cleanupPM", t);
+        }
+ + try {
+            localTearDown();
+ } + catch (Throwable t) {
+            setTearDownThrowable("localTearDown", t);
+        }
+ + try {
            closePMF();
        }
-        catch (Throwable ex) {
-            if (debug) ex.printStackTrace();
+        catch (Throwable t) {
+            setTearDownThrowable("closePMF", t);
+        }
+ + if (this.tearDownThrowable != null) {
+            Throwable t = this.tearDownThrowable;
+            this.tearDownThrowable = null;
            if (testSucceeded) {
-                // runTest succeeded, but closePMF throws exception =>
-                // failure
-                fail("Exception during tearDown: " + ex);
+                // runTest succeeded, but this method threw exception => error
+                throw new JDOFatalException("Exception during tearDown", t);
            }
-            else {
-                // runTest failed and closePMF throws exception =>
-                // just print the closePMF exception, otherwise the
-                // closePMF exception would swallow the test case failure
-                if (debug) logger.debug("Exception during tearDown: " + ex);
+        }
+    }
+
+ /** + * Deletes all registered pc instances and extents of all registered pc classes. + * Subclasses may override this method to clear any data and resources
+     * that they have allocated in method <code>localSetUp</code>.
+     */
+    protected void localTearDown() {
+        deleteAndUnregisterPCInstances();
+        deleteAndUnregisterPCClasses();
+    }
+
+    protected void addTearDownObjectId(Object oid) {
+        // ensure that oid is not a PC instance
+        if (JDOHelper.getObjectId(oid) != null ||
+            JDOHelper.isTransactional(oid))
+            throw new IllegalArgumentException("oid");
+        this.oids.add(oid);
+    }
+ + protected void addTearDownInstance(Object pc) {
+        Object oid = JDOHelper.getObjectId(pc);
+        addTearDownObjectId(oid);
+    }
+ + protected void addTearDownClass(Class pcClass) {
+        this.pcClasses.add(pcClass);
+    }
+ + /** + * Deletes and unregistres all registered pc instances. + */
+    protected void deleteAndUnregisterPCInstances() {
+        getPM();
+        try {
+            this.pm.currentTransaction().begin();
+            for (Iterator i = this.oids.iterator(); i.hasNext(); ) {
+                Object pc;
+                try {
+                    pc = this.pm.getObjectById(i.next(), true);
+                }
+                catch (JDOObjectNotFoundException e) {
+                    pc = null;
+                }
+                // we only delete those persistent instances
+                // which have not been deleted by tests already.
+                if (pc != null) {
+                    this.pm.deletePersistent(pc);
+                }
            }
+            this.pm.currentTransaction().commit();
        }
+        finally {
+            this.oids.clear();
+            cleanupPM();
+        }
    }

    /**
+ * Deletes extents of all registered pc instances and unregisters all pc classes. + */
+    protected void deleteAndUnregisterPCClasses() {
+        getPM();
+        try {
+            this.pm.currentTransaction().begin();
+            for (Iterator i = this.pcClasses.iterator(); i.hasNext(); ) {
+                this.pm.deletePersistentAll(getAllObjects(this.pm, 
(Class)i.next()));
+            }
+            this.pm.currentTransaction().commit();
+        }
+        finally {
+            this.pcClasses.clear();
+            cleanupPM();
+        }
+    }
+
+    /** */
+    protected Collection getAllObjects(PersistenceManager pm, Class pcClass) {
+        Collection col = new Vector() ;
+        Query query = pm.newQuery();
+        query.setClass(pcClass);
+        query.setCandidates(pm.getExtent(pcClass, false));
+        Object result = query.execute();
+        return (Collection)result;
+    }
+
+    /**
* Get the <code>PersistenceManagerFactory</code> instance * for the implementation under test.
     */
@@ -209,7 +372,7 @@
     * multiple PersistenceManager instances around, in case the
* PersistenceManagerFactory performs PersistenceManager pooling. */ - protected void cleanup() + protected void cleanupPM() {
        cleanupPM(pm);
        pm = null;
@@ -220,7 +383,7 @@
     * <code>PersistenceManager</code>. If the pm still has an open
     * transaction, it will be rolled back, before closing the pm.
     */
- protected void cleanupPM(PersistenceManager pm) + protected static void cleanupPM(PersistenceManager pm) {
        if ((pm != null) && !pm.isClosed()) {
            if (pm.currentTransaction().isActive()) {

Reply via email to