svn commit: r160090 [13/63] - in incubator/jdo/trunk: ./ tck20/ tck20/assertions/ tck20/iut_jars/ tck20/test/ tck20/test/conf/ tck20/test/java/ tck20/test/java/org/ tck20/test/java/org/apache/ tck20/test/java/org/apache/jdo/ tck20/test/java/org/apache/jdo/tck/ tck20/test/java/org/apache/jdo/tck/api/ tck20/test/java/org/apache/jdo/tck/api/instancecallbacks/ tck20/test/java/org/apache/jdo/tck/api/jdohelper/ tck20/test/java/org/apache/jdo/tck/api/persistencemanager/ tck20/test/java/org/apache/jdo/tck/api/persistencemanager/cache/ tck20/test/java/org/apache/jdo/tck/api/persistencemanager/close/ tck20/test/java/org/apache/jdo/tck/api/persistencemanager/extent/ tck20/test/java/org/apache/jdo/tck/api/persistencemanager/flags/ tck20/test/java/org/apache/jdo/tck/api/persistencemanager/getobject/ tck20/test/java/org/apache/jdo/tck/api/persistencemanager/lifecycle/ tck20/test/java/org/apache/jdo/tck/api/persistencemanagerfactory/ tck20/test/java/org/apache/jdo/tck/enhancement/ tck20/test/java/org/apache/jdo/tck/extents/ tck20/test/java/org/apache/jdo/tck/lifecycle/ tck20/test/java/org/apache/jdo/tck/lifecycle/nontransactional/ tck20/test/java/org/apache/jdo/tck/models/ tck20/test/java/org/apache/jdo/tck/models/embedded/ tck20/test/java/org/apache/jdo/tck/models/fieldtypes/ tck20/test/java/org/apache/jdo/tck/models/inheritance/ tck20/test/java/org/apache/jdo/tck/pc/ tck20/test/java/org/apache/jdo/tck/pc/company/ tck20/test/java/org/apache/jdo/tck/pc/fieldtypes/ tck20/test/java/org/apache/jdo/tck/pc/inheritance/ tck20/test/java/org/apache/jdo/tck/pc/instancecallbacks/ tck20/test/java/org/apache/jdo/tck/pc/lifecycle/ tck20/test/java/org/apache/jdo/tck/pc/mylib/ tck20/test/java/org/apache/jdo/tck/query/ tck20/test/java/org/apache/jdo/tck/query/operators/ tck20/test/java/org/apache/jdo/tck/transactions/ tck20/test/java/org/apache/jdo/tck/util/ tck20/test/jdo/ tck20/test/jdo/applicationidentity/ tck20/test/jdo/applicationidentity/org/ tck20/test/jdo/applicationidentity/org/apache/ tck20/test/jdo/applicationidentity/org/apache/jdo/ tck20/test/jdo/applicationidentity/org/apache/jdo/tck/ tck20/test/jdo/applicationidentity/org/apache/jdo/tck/pc/ tck20/test/jdo/applicationidentity/org/apache/jdo/tck/pc/company/ tck20/test/jdo/applicationidentity/org/apache/jdo/tck/pc/fieldtypes/ tck20/test/jdo/applicationidentity/org/apache/jdo/tck/pc/inheritance/ tck20/test/jdo/applicationidentity/org/apache/jdo/tck/pc/instancecallbacks/ tck20/test/jdo/applicationidentity/org/apache/jdo/tck/pc/lifecycle/ tck20/test/jdo/applicationidentity/org/apache/jdo/tck/pc/mylib/ tck20/test/jdo/datastoreidentity/ tck20/test/jdo/datastoreidentity/org/ tck20/test/jdo/datastoreidentity/org/apache/ tck20/test/jdo/datastoreidentity/org/apache/jdo/ tck20/test/jdo/datastoreidentity/org/apache/jdo/tck/ tck20/test/jdo/datastoreidentity/org/apache/jdo/tck/pc/ tck20/test/jdo/datastoreidentity/org/apache/jdo/tck/pc/company/ tck20/test/jdo/datastoreidentity/org/apache/jdo/tck/pc/fieldtypes/ tck20/test/jdo/datastoreidentity/org/apache/jdo/tck/pc/inheritance/ tck20/test/jdo/datastoreidentity/org/apache/jdo/tck/pc/instancecallbacks/ tck20/test/jdo/datastoreidentity/org/apache/jdo/tck/pc/lifecycle/ tck20/test/jdo/datastoreidentity/org/apache/jdo/tck/pc/mylib/ tck20/test/orm/ tck20/test/orm/applicationidentity/ tck20/test/orm/applicationidentity/org/ tck20/test/orm/applicationidentity/org/apache/ tck20/test/orm/applicationidentity/org/apache/jdo/ tck20/test/orm/applicationidentity/org/apache/jdo/tck/ tck20/test/orm/applicationidentity/org/apache/jdo/tck/pc/ tck20/test/orm/applicationidentity/org/apache/jdo/tck/pc/company/ tck20/test/orm/applicationidentity/org/apache/jdo/tck/pc/fieldtypes/ tck20/test/orm/applicationidentity/org/apache/jdo/tck/pc/inheritance/ tck20/test/orm/applicationidentity/org/apache/jdo/tck/pc/instancecallbacks/ tck20/test/orm/applicationidentity/org/apache/jdo/tck/pc/lifecycle/ tck20/test/orm/applicationidentity/org/apache/jdo/tck/pc/mylib/ tck20/test/orm/datastoreidentity/ tck20/test/orm/datastoreidentity/org/ tck20/test/orm/datastoreidentity/org/apache/ tck20/test/orm/datastoreidentity/org/apache/jdo/ tck20/test/orm/datastoreidentity/org/apache/jdo/tck/ tck20/test/orm/datastoreidentity/org/apache/jdo/tck/pc/ tck20/test/orm/datastoreidentity/org/apache/jdo/tck/pc/company/ tck20/test/orm/datastoreidentity/org/apache/jdo/tck/pc/fieldtypes/ tck20/test/orm/datastoreidentity/org/apache/jdo/tck/pc/inheritance/ tck20/test/orm/datastoreidentity/org/apache/jdo/tck/pc/instancecallbacks/ tck20/test/orm/datastoreidentity/org/apache/jdo/tck/pc/lifecycle/ tck20/test/orm/datastoreidentity/org/apache/jdo/tck/pc/mylib/ tck20/test/sql/ tck20/test/sql/derby/

4 Apr 2005 20:10:33 -0000

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorMutatingMethods.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentClose.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentClose.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentClose.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentClose.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.tck.extents;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.jdo.Extent;
+
+import org.apache.jdo.tck.pc.company.Employee;
+import org.apache.jdo.tck.util.BatchTestRunner;
+
+/**
+ *<B>Title:</B> Iterator Next After Extent Close
+ *<BR>
+ *<B>Keywords:</B> extent exception
+ *<BR>
+ *<B>Assertion ID:</B> A15.3-10.
+ *<BR>
+ *<B>Assertion Description: </B>
+After a call to <code>Extent.close(Iterator i)</code>,
+the parameter <code>Iterator</code>
+will throw a <code>NoSuchElementException</code> to <code>next()</code>. 
+
+ */
+
+public class IteratorNextAfterExtentClose extends ExtentTest {
+
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertion A15.3-10 (IteratorNextAfterExtentClose) failed: ";
+    
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+        BatchTestRunner.run(IteratorNextAfterExtentClose.class);
+    }
+
+    /** */
+    public void test() {
+
+        try {
+            beginTransaction();
+            Extent ex = getPM().getExtent (Employee.class, true);
+            Iterator it1 = ex.iterator();
+            deleteEmployee((Employee)it1.next());
+            Iterator it2 = ex.iterator();
+            addEmployee();
+            Iterator it3 = ex.iterator();
+            ex.close(it1);
+            ex.close(it2);
+            ex.close(it3);
+
+            try {
+                tryNext(it1);
+                tryNext(it2);
+                tryNext(it3);
+                rollbackTransaction();
+    
+                Iterator it4 = ex.iterator();
+                int count4 = countIterator(it4);
+                if (count4 != 2) {
+                    fail(ASSERTION_FAILED,
+                         "Iterator4 after rollback: " + count4 + "; should be 
2");
+                }
+            } 
+            catch (Exception unexpected) {
+                rollbackTransaction();
+                cleanup();
+                fail(ASSERTION_FAILED,
+                     "unexpected exception " + unexpected);
+            }
+        } 
+        catch (Exception unexpected) {
+            fail(ASSERTION_FAILED,
+                 "unexpected exception " + unexpected);
+        } 
+        finally  {
+            cleanup();
+        }
+    }
+
+    /** */
+    void tryNext (Iterator it) throws Exception {
+        try {
+            it.next();
+            fail(ASSERTION_FAILED,
+                 "expected NoSuchElementException thrown by iterator.next().");
+        } catch (NoSuchElementException expected) {
+            // expecteed exception
+        }
+    }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentClose.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentCloseAll.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentCloseAll.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentCloseAll.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentCloseAll.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.tck.extents;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import javax.jdo.Extent;
+
+import org.apache.jdo.tck.pc.company.Employee;
+import org.apache.jdo.tck.util.BatchTestRunner;
+
+/**
+ *<B>Title:</B> Iterator Next After Extent CloseAll
+ *<BR>
+ *<B>Keywords:</B> extent
+ *<BR>
+ *<B>Assertion ID:</B> A15.3-13.
+ *<BR>
+ *<B>Assertion Description: </B>
+After a call to <code>Extent.closeAll()</code>, all iterators acquired from 
this
+<code>Extent</code> will throw a <code>NoSuchElementException</code>
+to <code>next()</code>.
+
+ */
+
+public class IteratorNextAfterExtentCloseAll extends ExtentTest {
+
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertion A15.3-13 (IteratorNextAfterExtentCloseAll) failed: ";
+    
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+        BatchTestRunner.run(IteratorNextAfterExtentCloseAll.class);
+    }
+
+    /** */
+    public void test() {
+
+        try {
+            beginTransaction();
+            Extent ex = getPM().getExtent (Employee.class, true);
+            Iterator it1 = ex.iterator();
+            deleteEmployee((Employee)it1.next());
+            Iterator it2 = ex.iterator();
+            addEmployee();
+            Iterator it3 = ex.iterator();
+            ex.closeAll();
+
+            if (!tryNext(it1)) {
+                fail(ASSERTION_FAILED,
+                     "iterator1.next() does not throw 
NoSuchElementException.");
+            }
+            if (!tryNext(it2)) {
+                fail(ASSERTION_FAILED,
+                     "iterator2.next() does not throw 
NoSuchElementException.");
+            }
+            if (!tryNext(it3)) {
+                fail(ASSERTION_FAILED,
+                     "iterator3.next() does not throw 
NoSuchElementException.");
+            }
+        } 
+        finally  {
+            rollbackTransaction();
+            cleanup();
+        }
+    }
+    
+    /** */
+    boolean tryNext (Iterator it) {
+        try {
+            it.next();
+        } catch (NoSuchElementException expected) {
+            return true;
+        }
+        return false;
+    }
+
+}
+

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/IteratorNextAfterExtentCloseAll.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/Iterators.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/Iterators.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/Iterators.java 
(added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/Iterators.java 
Mon Apr  4 12:41:23 2005
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+
+package org.apache.jdo.tck.extents;
+
+import java.util.Iterator;
+
+import javax.jdo.Extent;
+
+import org.apache.jdo.tck.util.BatchTestRunner;
+
+/**
+ *<B>Title:</B> Iterators
+ *<BR>
+ *<B>Keywords:</B> extent
+ *<BR>
+ *<B>Assertion ID:</B> A15.3-1.
+ *<BR>
+ *<B>Assertion Description: </B>
+<code>Extent.iterator()</code> returns an <code>Iterator</code>
+over all the instances in the <code>Extent</code>.
+
+ */
+
+public class Iterators extends ExtentTest {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertion A15.3-1 (Iterators) failed: ";
+    
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+        BatchTestRunner.run(Iterators.class);
+    }
+
+    /** */
+    public void test() {
+
+        Extent ex = getExtent();
+    
+        int count = 0;
+        for (Iterator it = ex.iterator(); it.hasNext();++count) {
+            Object emp = it.next();
+            if (debug) logger.debug(emp.toString());
+        }
+    
+        if (count != 2) {
+            fail(ASSERTION_FAILED,
+                 "Emplyoee extent should have 2 instances, got " + count);
+        }
+    }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/extents/Iterators.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/HollowInstanceMaintainsPK.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/HollowInstanceMaintainsPK.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/HollowInstanceMaintainsPK.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/HollowInstanceMaintainsPK.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ 
+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.util.BatchTestRunner;
+
+/**
+ *<B>Title:</B> Test that Hollow Instances maintains PK
+ *<BR>
+ *<B>Keywords:</B> lifecycle hollow instance PK
+ *<BR>
+ *<B>Assertion IDs:</B> A5.5.4-3
+ *<BR>
+ *<B>Assertion Description: </B>
+ If the instance is of a class using application identity, the hollow instance 
maintains its primary key fields.
+ */
+
+public class HollowInstanceMaintainsPK extends JDO_Test {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertion A5.5.4-3 (HollowInstanceMaintainsPK) failed: ";
+    
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+        BatchTestRunner.run(HollowInstanceMaintainsPK.class);
+    }
+
+    /** */
+    public void test() {
+        if (!isApplicationIdentitySupported()) {
+            if (debug) logger.debug("Application Identity is not supported");
+        }
+        else {
+            pm = getPM();
+            pm.currentTransaction().begin();
+
+            PCRect obj = getPersistentNewInstance();
+
+            long beforeValue=obj.getId();
+            pm.currentTransaction().commit(); // obj should transition to 
HOLLOW
+            long afterValue=obj.getId();
+            if (beforeValue!=afterValue) {
+                fail(ASSERTION_FAILED,
+                     "Key field value incorrect after commit. Expected: " + 
+                     beforeValue + " Found: " + afterValue);
+            }
+        }
+    }
+
+    /** */
+    private PCRect getPersistentNewInstance() {
+        PCRect obj = new PCRect();
+        pm.makePersistent(obj); // obj should transition to persistent-new
+        int curr = currentState(obj);
+        if( curr != PERSISTENT_NEW ){
+            fail(ASSERTION_FAILED,
+                 "StateTransitions: Unable to create persistent-new instance " 
+
+                 "from transient instance via makePersistent(), state is " +
+                 states[curr]);
+        }
+        return obj;
+    }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/HollowInstanceMaintainsPK.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/MultiplePMsReturnInstancesRepresentingSamePC.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/MultiplePMsReturnInstancesRepresentingSamePC.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/MultiplePMsReturnInstancesRepresentingSamePC.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/MultiplePMsReturnInstancesRepresentingSamePC.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ 
+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;
+
+/**
+ *<B>Title:</B> Test that Multiple PMs return different instances representing 
same PC object
+ *<BR>
+ *<B>Keywords:</B> lifecycle Multiple PMs getObjectById equal
+ *<BR>
+ *<B>Assertion IDs:</B> A5.4-7
+ *<BR>
+ *<B>Assertion Description: </B>
+ The instance returned by a call to getObjectById(Object) of different 
PersistenceManager 
+ instances returned by the same PersistenceManagerFactory represent the same 
persistent object, 
+ but with different Java object identity (specifically, all instances returned 
by getObjectId from the instances
+ must return true to equals comparisons with all others).
+ */
+
+public class MultiplePMsReturnInstancesRepresentingSamePC extends JDO_Test {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertion A5.4-7 (MultiplePMsReturnInstancesRepresentingSamePC) 
failed: ";
+
+       private static final int NUM_OBJECTS = 50;
+
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+               
BatchTestRunner.run(MultiplePMsReturnInstancesRepresentingSamePC.class);
+    }
+
+    public MultiplePMsReturnInstancesRepresentingSamePC()
+    {
+    }
+
+       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() ){
+                               fail(ASSERTION_FAILED,
+                                        "Extent for StateTransitionObj should 
not be empty");
+                       }
+                       extent.close(iter);
+
+
+                       for (int i=0; i<NUM_OBJECTS; i++)
+                       {
+                               Object obj1 = obj[i];
+                               Object objId1 = pm.getObjectId(obj1);
+                               Object obj2 = pm2.getObjectById(objId1,false);
+                               Object objId2 = pm2.getObjectId(obj2);
+                               Object obj3 = pm3.getObjectById(objId1,false);
+                               Object objId3 = pm3.getObjectId(obj3);
+                               
+                               //Verify that objects are different instances
+                               if (!((obj1!=obj2) && (obj1!=obj3)))
+                               {
+                                       fail(ASSERTION_FAILED,
+                                                "Objects are not different 
instances. obj1=" + obj1 + " obj2= " + obj2 + " obj3= " + obj3);
+                               }
+                               
+                               //Verify that object Ids are equal
+                               if (!(objId1.equals(objId2) && 
objId1.equals(objId3)))
+                               {
+                                       fail(ASSERTION_FAILED,
+                                                "Object Ids are not equal. 
objId1=" + objId1 + " objId2= " + objId2 + " objId3= " + objId3);
+                               }
+                       }
+           }
+           finally {
+               if (pm2!=null && !pm2.isClosed())
+               {
+                   pm2.close();
+               }
+               if (pm3!=null && !pm3.isClosed())
+               {
+                   pm3.close();
+               }                       
+           }
+       }
+
+       private Object[] generatePersistentInstances()
+       {
+               StateTransitionObj[] objects = new 
StateTransitionObj[NUM_OBJECTS];
+               try {
+                   Transaction t = pm.currentTransaction();
+                   t.begin();
+                   for(int i = 0; i < NUM_OBJECTS; ++i ){
+                               objects[i]=new StateTransitionObj(i);
+                       objects[i].writeField(i);
+                       pm.makePersistent(objects[i]);
+                   }
+                   t.commit();
+                       return objects;
+               }
+               finally {
+                Transaction tx = pm.currentTransaction();
+                if (tx.isActive()) {
+                    tx.rollback();
+                }
+               }
+       }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/MultiplePMsReturnInstancesRepresentingSamePC.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ 
+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;
+
+/**
+ *<B>Title:</B> Test that ObjectId is not modified even if ObjectId returned 
by GetObjectId() is modified
+ *<BR>
+ *<B>Keywords:</B> lifecycle GetObjectId
+ *<BR>
+ *<B>Assertion IDs:</B> A5.4-6
+ *<BR>
+ *<B>Assertion Description: </B>
+ The object returned by any call to getObjectId might be modified by the user, 
+ but that modification does not affect the identity of the object that was 
originally referred.
+ */
+
+public class ObjectIdNotModifiedWhenObjectIdInstanceModified extends JDO_Test {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertion A5.4-6 (ObjectIdNotModifiedWhenObjectIdInstanceModified) 
failed: ";
+               
+       private static final int NUM_OBJECTS = 50;
+
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+               
BatchTestRunner.run(ObjectIdNotModifiedWhenObjectIdInstanceModified.class);
+    }
+
+    public ObjectIdNotModifiedWhenObjectIdInstanceModified()
+    {
+    }
+
+       public void test() throws Exception {
+               pm = getPM();
+               
+               Object[] obj = generatePersistentInstances();
+
+               Extent extent = pm.getExtent(StateTransitionObj.class, false);
+               Iterator iter = extent.iterator();
+               if( !iter.hasNext() ){
+                       fail(ASSERTION_FAILED,
+                                "Extent for StateTransitionObj should not be 
empty");
+               }
+               extent.close(iter);
+
+               for (int i=0; i<NUM_OBJECTS; i++)
+               {
+                       Object objId=pm.getObjectId(obj[i]);
+                       mangleObject(objId);
+                       Object objId2 = pm.getObjectId(obj[i]); // get another 
ObjectId copy
+                       if (objId.equals(objId2))
+                               fail(ASSERTION_FAILED,
+                                        "object Id has been changed");
+               }
+       }
+
+       private Object[] generatePersistentInstances()
+       {
+               StateTransitionObj[] objects = new 
StateTransitionObj[NUM_OBJECTS];
+               try {
+                   Transaction t = pm.currentTransaction();
+                   t.begin();
+                   for(int i = 0; i < NUM_OBJECTS; ++i ){
+                               objects[i]=new StateTransitionObj(i);
+                       objects[i].writeField(i);
+                       pm.makePersistent(objects[i]);
+                   }
+                   t.commit();
+                       return objects;
+               }
+               finally {
+                Transaction tx = pm.currentTransaction();
+                if (tx.isActive()) {
+                    tx.rollback();
+                }
+               }
+       }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/ObjectIdNotModifiedWhenObjectIdInstanceModified.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMReturnsIdenticalInstancesForEqualObjIds.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMReturnsIdenticalInstancesForEqualObjIds.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMReturnsIdenticalInstancesForEqualObjIds.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMReturnsIdenticalInstancesForEqualObjIds.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ 
+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;
+
+/**
+ *<B>Title:</B> Test that a PM returns the same JDO instance if 
getObjectById(ObjectId) is called multiple times with the same objectId instance
+ *<BR>
+ *<B>Keywords:</B> lifecycle getObjectById
+ *<BR>
+ *<B>Assertion IDs:</B> A5.4-2, A5.4-8, A5.4-10
+ *<BR>
+ *<B>Assertion Description: </B>
+ Any instances returned by any calls to getObjectById(Object) with the same 
object id instance to the same
+ PersistenceManager instance must be identical (assuming the instances were 
not garbage collected between calls).
+ */
+
+public class PMReturnsIdenticalInstancesForEqualObjIds extends JDO_Test {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertions A5.4-2, A5.4-8, A5.4-10 
(PMReturnsIdenticalInstancesForEqualObjIds) failed: ";
+    
+       private static final int NUM_OBJECTS = 50;
+
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+               
BatchTestRunner.run(PMReturnsIdenticalInstancesForEqualObjIds.class);
+    }
+
+    public PMReturnsIdenticalInstancesForEqualObjIds()
+    {
+    }
+
+       public void test() {
+           pm = getPM();
+
+           Object[] obj = generatePersistentInstances();
+
+       Extent extent = pm.getExtent(StateTransitionObj.class, false);
+       Iterator iter = extent.iterator();
+       if( !iter.hasNext() ){
+               fail(ASSERTION_FAILED,
+                                "Extent for StateTransitionObj should not be 
empty");
+       }
+               extent.close(iter);
+
+               for (int i=0; i<NUM_OBJECTS; i++)
+               {
+                       Object objId=pm.getObjectId(obj[i]);
+                       // check that getObjectById returns identical instance
+                       Object obj2 = pm.getObjectById(objId, true);
+                       if (!(obj2==obj[i]))
+                       {
+                               fail(ASSERTION_FAILED,
+                                        "objects with OId = " + objId + " are 
not identical");
+                       }
+               }
+       }
+
+       private Object[] generatePersistentInstances()
+       {
+               StateTransitionObj[] objects = new 
StateTransitionObj[NUM_OBJECTS];
+               try {
+                   Transaction t = pm.currentTransaction();
+                   t.begin();
+                   for(int i = 0; i < NUM_OBJECTS; ++i ){
+                               objects[i]=new StateTransitionObj(i);
+                       objects[i].writeField(i);
+                       pm.makePersistent(objects[i]);
+                   }
+                   t.commit();
+                       return objects;
+               }
+               finally {
+                Transaction tx = pm.currentTransaction();
+                if (tx.isActive()) {
+                    tx.rollback();
+                }
+               }
+       }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMReturnsIdenticalInstancesForEqualObjIds.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMsCanSharePCClassesButNotPCInstances.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMsCanSharePCClassesButNotPCInstances.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMsCanSharePCClassesButNotPCInstances.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMsCanSharePCClassesButNotPCInstances.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,230 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ 
+package org.apache.jdo.tck.lifecycle;
+
+import java.util.*;
+import javax.jdo.*;
+
+import org.apache.jdo.tck.JDO_Test;
+import org.apache.jdo.tck.pc.lifecycle.StateTransitionObj;
+import org.apache.jdo.tck.util.BatchTestRunner;
+import org.apache.jdo.tck.util.ThreadExceptionHandler;
+
+/**
+ *<B>Title:</B> Test PM ability to share PC classes but not PC instances
+ *<BR>
+ *<B>Keywords:</B> PM share PC class
+ *<BR>
+ *<B>Assertion IDs:</B> A5.2-1,A5.2-2,A5.2-3
+ *<BR>
+ *<B>Assertion Description: </B>
+ Several JDO PersistenceManagers might be coresident and might
+ share the same persistence capable classes] (although a JDO instance can be
+ associated with only one PersistenceManager at a time)
+ */
+
+public class PMsCanSharePCClassesButNotPCInstances extends JDO_Test {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertions A5.2-1,A5.2-2,A5.2-3 
(PMsCanSharePCClassesButNotPCInstances) failed: ";
+
+    /** The number of active threads. Each thread has its own PM. */
+    private int threads = 0;
+
+    /** The total number of attempts to insert PC instances */
+    private int attempts = 0;
+
+    /** The number of inserters. Each inserter runs in its own thread. */
+    private int inserters = 5;
+
+    /** The number of objects inserted. */
+    protected int insertedCount = 0;
+
+    /** The number of objects that is expected to have been inserted. */
+    protected int insertedCountExpected = 0;
+
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+        BatchTestRunner.run(PMsCanSharePCClassesButNotPCInstances.class);
+    }
+
+    public PMsCanSharePCClassesButNotPCInstances()
+    {
+    }
+
+    public void test() {
+        // test shared PC - only one PM should succeed to insert the shared PC
+        threads = 0;
+        attempts = 0;
+        insertedCount = 0;
+        insertedCountExpected = 1;
+        insertObjects(true);
+        
+        // test non-shared PCs - each PM should succeed to insert its own 
non-shared PC
+        threads = 0;
+        attempts = 0;
+        //insertedCount = 0; //Don't reset this value since we have not 
deleted the inserted object from the shared PC test above
+        insertedCountExpected += inserters;
+        insertObjects(false);
+    }
+
+    protected void insertObjects(boolean sharedPC) {
+        Object pc = null;
+
+        ThreadExceptionHandler threadGroup = new ThreadExceptionHandler();
+        for (int i = 0; i < inserters; i++) {
+            if (sharedPC) { // each thread shares one PC
+                if (pc==null)
+                    pc = new StateTransitionObj(i);
+            }
+            else { // each thread has its own PC
+                pc = new StateTransitionObj(i);
+            }
+            threads++;
+            Thread t = new Thread(threadGroup, new Inserter(pmf, pc, 
sharedPC));
+            t.setName("Inserter-" + i);
+            t.start();
+        }
+        
+        Thread.currentThread().yield();
+        
+        while (! attemptsComplete()) { 
+            try  {
+                Thread.currentThread().sleep(100);
+            } catch (InterruptedException ex) {
+                logger.debug("interrupted while waiting for threads to 
insert");
+            }
+        }
+
+        while (threads > 0) {
+            try {
+                Thread.currentThread().sleep(100);
+            } catch (InterruptedException ex) {
+                logger.debug("interrupted while waiting for threads to 
finish");
+            }
+        }
+    }
+
+    synchronized void signal() {
+        threads--;
+    }
+
+    protected synchronized void incrAttempts() {
+        attempts++;
+    }
+
+    protected synchronized boolean attemptsComplete() {
+        return attempts == inserters;
+    }
+
+    class Inserter implements Runnable {
+        private final PersistenceManager pm;
+        private final Object pc;
+        private final Class instanceClass;
+        private final boolean sharedPC;
+
+        Inserter(PersistenceManagerFactory pmf, Object pc, boolean sharedPC) {
+            this.pm = pmf.getPersistenceManager();
+            this.pc = pc;
+            this.instanceClass = pc.getClass();
+            this.sharedPC = sharedPC;
+        }
+
+        protected synchronized void announce(String msg, Object pc) {
+            insertedCount++;
+            Object oid = JDOHelper.getObjectId(pc);
+            if (debug)
+                logger.debug(msg + this.getClass().getName() + ": " + oid +
+                             ", " + pc);
+        }
+
+        public void run() {
+            Transaction tx = null;
+            try {
+                if (debug) logger.debug("running");
+                tx = pm.currentTransaction();
+                tx.begin();
+                try {
+                    pm.makePersistent(pc);
+                    announce("inserted ", pc);
+                    tx.commit();
+                }
+                catch (JDOException ex) {
+                    if (!sharedPC) //we expect an exception for all but one of 
the inserters in the case of a shared PC
+                        throw ex;
+                }
+                finally {
+                    if (tx != null && tx.isActive())
+                        tx.rollback();
+                }
+                incrAttempts();
+
+                while (!attemptsComplete()) {
+                    try {
+                        Thread.currentThread().sleep(100);
+                    } catch (InterruptedException ex) {
+                        if (debug) logger.debug(" interrupted");
+                    }
+                }
+
+                //Verify that the number of inserted objects matches the 
expected number
+                if (insertedCount!=insertedCountExpected)
+                {
+                    fail(ASSERTION_FAILED,
+                         "Wrong number of objects in extent. Inserted=" + 
+                         insertedCount + " Expected=" + insertedCountExpected);
+                }
+
+                if (debug) logger.debug("getting Extent");
+                int objCount = 0;
+                if (debug)
+                    logger.debug("getting Extent of " + 
instanceClass.getName());
+                Extent e = pm.getExtent(instanceClass, false);
+                for (Iterator i = e.iterator(); i.hasNext();) {
+                    Object instance = (Object)i.next();
+                    objCount++;
+                }
+
+                //Verify that the number of inserted objects matches the 
number of objects in the extent
+                if (insertedCount!=objCount)
+                {
+                    fail(ASSERTION_FAILED,
+                         "Wrong number of objects in extent. 
Inserted="+insertedCount+" Found="+objCount);
+                }
+            } finally {
+                if (tx != null && tx.isActive())
+                    tx.rollback();
+                if (pm != null && !pm.isClosed())
+                    pm.close();
+                PMsCanSharePCClassesButNotPCInstances.this.signal();
+            }
+        }
+
+        public String toString() {
+            String rc = "Inserter ";
+            if (debug) {
+                rc += Thread.currentThread().toString();
+            }
+            return rc;
+        }
+    }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/PMsCanSharePCClassesButNotPCInstances.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/StateTransitions.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/StateTransitions.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/StateTransitions.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/StateTransitions.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,768 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ 
+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;
+
+/**
+ *<B>Title:</B> Test State Transitions
+ *<BR>
+ *<B>Keywords:</B> lifecycle
+ *<BR>
+ *<B>Assertion IDs:</B> A5.9-1 through A5.9-190
+ *<B>Assertion Description: </B>
+ All possible state transistions are being tested in this test.
+ */
+
+public class StateTransitions extends JDO_Test {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertions A5.9-1 through A5.9-190 (StateTransitions) failed: ";
+    
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+        BatchTestRunner.run(StateTransitions.class);
+    }
+    
+    private Transaction                 transaction;
+    private int                         scenario;
+    private int                         operation;
+    private int                         current_state;
+    private int                         expected_state;
+    private int                         new_state;
+
+/**
+ * Operations that cause state changes
+ */
+    private static final int MAKEPERSISTENT          = 0;
+    private static final int DELETEPERSISTENT        = 1;
+    private static final int MAKETRANSACTIONAL       = 2;
+    private static final int MAKENONTRANSACTIONAL    = 3;
+    private static final int MAKETRANSIENT           = 4;
+    private static final int COMMITNORETAINVALUES    = 5;
+    private static final int COMMITRETAINVALUES      = 6;
+    private static final int ROLLBACKNORESTOREVALUES = 7;
+    private static final int ROLLBACKRESTOREVALUES   = 8;
+    private static final int REFRESHDATASTORE        = 9;
+    private static final int REFRESHOPTIMISTIC       = 10;
+    private static final int EVICT                   = 11;
+    private static final int READOUTSIDETX           = 12;
+    private static final int READOPTIMISTIC          = 13;
+    private static final int READDATASTORE           = 14;
+    private static final int WRITEOUTSIDETX          = 15;
+    private static final int WRITEINSIDETX           = 16;
+    private static final int RETRIEVEOUTSIDETX       = 17;
+    private static final int RETRIEVEINSIDETX        = 18;
+
+    private static final String[] operations = {
+        "makePersistent",
+        "deletePersistent",
+        "makeTransactional",
+        "makeNontransactional",
+        "makeTransient",
+        "commit, retainValues=false",
+        "commit, retainValues=true",
+        "rollback, restoreValues=false",
+        "rollback, restoreValues=true",
+        "refresh with active datastore tx",
+        "refresh with active optimistic tx",
+        "evict",
+        "read field outside tx",
+        "read field with active optimistic tx",
+        "read field with active datastore tx",
+        "write field outside tx",
+        "write field with active tx",
+        "retrieve outside tx",
+        "retrieve with active tx"
+    };
+    private static final int NUM_OPERATIONS = 19;
+
+    private static final boolean[] closes_transaction =
+    { false, false, false, false, false, true, true, true, true, false,
+      false, false, false, false, false, false, false, false, false };
+
+    /**
+     * Illegal state transitions
+     */
+    private static final int UNCHANGED                   = -1;
+    private static final int ERROR                       = -2;
+    private static final int IMPOSSIBLE                  = -3;
+    private static final int NOT_APPLICABLE              = -4;
+
+    /**
+     * State transitions
+     */
+    public static final int[][] transitions = { // [operation] [current state] 
= new state
+        // makePersistent
+        { PERSISTENT_NEW, UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED, 
PERSISTENT_NEW,
+          PERSISTENT_NEW, UNCHANGED, UNCHANGED, UNCHANGED},
+
+        // deletePersistent
+        { ERROR, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED, 
PERSISTENT_DELETED,
+          PERSISTENT_DELETED, ERROR, ERROR, UNCHANGED, UNCHANGED, 
PERSISTENT_DELETED},
+
+        // makeTransactional
+        { TRANSIENT_CLEAN, UNCHANGED, UNCHANGED, UNCHANGED, PERSISTENT_CLEAN,
+          UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED, PERSISTENT_CLEAN},
+    
+        // makeNontransactional
+        { ERROR, ERROR, PERSISTENT_NONTRANSACTIONAL, ERROR, UNCHANGED,
+          TRANSIENT, ERROR, ERROR, ERROR, UNCHANGED},
+
+        // makeTransient
+        { UNCHANGED, ERROR, TRANSIENT, ERROR, TRANSIENT,
+          UNCHANGED, UNCHANGED, ERROR, ERROR, TRANSIENT},
+
+        // commit, retainValues = false
+        { UNCHANGED, HOLLOW, HOLLOW, HOLLOW, UNCHANGED, UNCHANGED,
+          TRANSIENT_CLEAN, TRANSIENT, TRANSIENT, UNCHANGED},
+
+        // commit, retainValues = true
+        { UNCHANGED, PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL,
+          PERSISTENT_NONTRANSACTIONAL, UNCHANGED, UNCHANGED, TRANSIENT_CLEAN,
+          TRANSIENT, TRANSIENT, UNCHANGED},
+
+        // rollback, restoreValues = false
+        { UNCHANGED, TRANSIENT, HOLLOW, HOLLOW, UNCHANGED, UNCHANGED,
+          TRANSIENT_CLEAN, TRANSIENT, HOLLOW, UNCHANGED},
+
+        // rollback, restoreValues = true
+        { UNCHANGED, TRANSIENT, PERSISTENT_NONTRANSACTIONAL, 
PERSISTENT_NONTRANSACTIONAL,
+          UNCHANGED, UNCHANGED, TRANSIENT_CLEAN, TRANSIENT, 
PERSISTENT_NONTRANSACTIONAL, UNCHANGED},
+
+        // refresh with active datastore transaction
+        { UNCHANGED, UNCHANGED, UNCHANGED, PERSISTENT_CLEAN, UNCHANGED,
+          UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED},
+
+        // refresh with active optimistic transaction
+        { UNCHANGED, UNCHANGED, UNCHANGED, PERSISTENT_NONTRANSACTIONAL, 
UNCHANGED,
+          UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED},
+
+        // evict
+        { NOT_APPLICABLE, UNCHANGED, HOLLOW, UNCHANGED, UNCHANGED,
+          UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED, HOLLOW},
+
+        // read field outside transaction
+        { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE, 
PERSISTENT_NONTRANSACTIONAL,
+          UNCHANGED, IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE, UNCHANGED},
+
+        // read field with active optimistic transaction
+        { UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED, 
PERSISTENT_NONTRANSACTIONAL,
+          UNCHANGED, UNCHANGED, ERROR, ERROR, UNCHANGED},
+
+        // read field with active datastore transaction
+        { UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED, PERSISTENT_CLEAN,
+          UNCHANGED, UNCHANGED, ERROR, ERROR, PERSISTENT_CLEAN},
+
+        // write field outside transaction
+        { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE, 
PERSISTENT_NONTRANSACTIONAL,
+          UNCHANGED, IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE, UNCHANGED},
+    
+        // write field with active transaction
+        { UNCHANGED, UNCHANGED, PERSISTENT_DIRTY, UNCHANGED, PERSISTENT_DIRTY,
+          TRANSIENT_DIRTY, UNCHANGED, ERROR, ERROR, PERSISTENT_DIRTY},
+         
+        // retrieve outside transaction
+        { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE, 
PERSISTENT_NONTRANSACTIONAL,
+          UNCHANGED, IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE, UNCHANGED},
+         
+        // retrieve with active transaction
+        { UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED, PERSISTENT_CLEAN,
+          UNCHANGED, UNCHANGED, UNCHANGED, UNCHANGED, PERSISTENT_CLEAN}
+    };
+
+    private static final int DATASTORE_TX = 0;
+    private static final int OPTIMISTIC_TX = 1;
+    private static final int NO_TX = 2;
+
+    private static final String[] scenario_string = {
+        "datastore transaction", "optimistic transaction", "no transaction"
+    };
+
+    private static final boolean[][] applies_to_scenario = {
+        //  Datastore   Optimistic      No tx
+        {   true,          true,        false },  // makePersistent
+        {   true,          true,        false },  // deletePersistent
+        {   true,          true,        false },  // makeTransactional
+        {   true,          true,        false },  // makeNontransactional
+        {   true,          true,        false },  // makeTransient
+        {   true,          true,        false },  // commit RetainValues = 
false
+        {   true,          true,        false },  // commit RetainValues = true
+        {   true,          true,        false },  // rollback RestoreValues = 
false
+        {   true,          true,        false },  // rollback RestoreValues = 
true
+        {   true,          false,       false },  // refresh with active 
datastore transaction
+        {   false,         true,        false },  // refresh with active 
optimistic transaction
+        {   true,          true,        false },  // evict
+        {   false,         false,       true  },  // read field outside of a 
transaction
+        {   false,         true,        false },  // read field with active 
optimistic transaction
+        {   true,          false,       false },  // read field with active 
datastore transaction
+        {   false,         false,       true  },  // write field or makeDirty 
outside of a transaction
+        {   true,          true,        false },  // write field or makeDirty 
with active transaction
+        {   false,         true,        true  },  // retrieve outside of a 
transaction or with active optimistic transaction
+        {   true,          false,       false }   // retrieve with active 
datastore transaction
+    };
+
+    public StateTransitions()
+    {
+    }
+
+    public void test() {
+        pm = getPM();
+        generatePersistentInstances();
+
+        scenario = DATASTORE_TX;
+        checkTransitions();
+
+        if( isOptimisticSupported() ){
+            scenario = OPTIMISTIC_TX;
+            checkTransitions();
+        }
+
+        scenario = NO_TX;
+        checkTransitions();
+    }
+
+    /** */
+    private void generatePersistentInstances()
+    {
+        if( doPersistentInstancesExist() ) return;
+        int i;
+        Transaction t = pm.currentTransaction();
+        t.begin();
+        for( i = 0; i < 50; ++i ){
+            StateTransitionObj sto = new StateTransitionObj(i);
+            sto.writeField(i);
+            pm.makePersistent(sto);
+        }
+        t.commit();
+        if( !doPersistentInstancesExist() )
+            if (debug)
+                logger.debug("StateTransitions unable to create instances of 
StateTransitionsObj");
+    }
+
+    /** */
+    private boolean doPersistentInstancesExist()
+    {
+        boolean ret;
+        Transaction t = pm.currentTransaction();
+        t.begin();
+        Extent e = pm.getExtent(StateTransitionObj.class, false);
+        Iterator iter = e.iterator();
+        ret = iter.hasNext();
+        t.rollback();
+        return ret;
+    }
+
+    /** */
+    void checkTransitions()
+    {
+        for( operation = 0; operation < NUM_OPERATIONS; ++operation ){
+            // rule out situations that do not apply
+            if( ! applies_to_scenario[operation][scenario] ) continue;
+            if( operation == READOUTSIDETX && 
!isNontransactionalReadSupported() ) continue;
+            if( operation == WRITEOUTSIDETX && 
!isNontransactionalWriteSupported() ) continue;
+            if( operation == COMMITRETAINVALUES && !isRetainValuesSupported() 
) continue;
+            if( operation == MAKENONTRANSACTIONAL &&
+                !(isNontransactionalReadSupported() || 
isNontransactionalWriteSupported()) )
+                continue;
+
+            for( current_state = 0; current_state < NUM_STATES; 
++current_state){
+                if( scenario == OPTIMISTIC_TX && current_state == 
PERSISTENT_CLEAN ) continue;
+                if( (current_state == TRANSIENT_CLEAN || current_state == 
TRANSIENT_DIRTY) &&
+                    !isTransientTransactionalSupported() )
+                    continue;   // this state is not supported by 
implementation
+                if( current_state == PERSISTENT_NONTRANSACTIONAL &&
+                    !(isNontransactionalReadSupported() || 
isNontransactionalWriteSupported()) )
+                    continue;   // this state is not supported by 
implementation
+
+                expected_state = transitions[operation][current_state];
+                if( expected_state == IMPOSSIBLE ) continue;
+                if( expected_state == NOT_APPLICABLE ) continue;
+                if( expected_state == UNCHANGED ) expected_state = 
current_state;
+                try {
+                    transaction = pm.currentTransaction();
+                    if( transaction.isActive()){
+                        if (debug)
+                            logger.debug("Transaction is active (but should 
not be), rolling back");
+                        transaction.rollback();
+                    }
+
+                    if( scenario != NO_TX ){
+                        if( operation == COMMITNORETAINVALUES )
+                            transaction.setRetainValues(false);
+                        if( operation == COMMITRETAINVALUES )
+                            transaction.setRetainValues(true);
+                        if( operation == ROLLBACKNORESTOREVALUES )
+                            transaction.setRestoreValues(false);
+                        if( operation == ROLLBACKRESTOREVALUES )
+                            transaction.setRestoreValues(true);
+
+                        transaction.setOptimistic(scenario == OPTIMISTIC_TX);
+                        transaction.begin();
+                        if( !transaction.isActive() )
+                            if (debug)
+                                logger.debug("StateTransitions: Transaction 
should be active, but it is not");
+                    }
+
+                    StateTransitionObj obj = getInstanceInState(current_state);
+                    if( obj == null ){  // could not get object in state
+                        if( transaction.isActive() ) transaction.rollback();
+                        continue;
+                    }
+
+                    // Apply operation, catching possible exception
+                    Exception e = null;
+                    try {
+                        applyOperation(operation, obj);
+                    } catch( Exception excep ){
+                        if( excep instanceof javax.jdo.JDOUserException ){
+                            e = excep;
+                        } else {
+                            printSituation();
+                            fail(ASSERTION_FAILED,
+                                 "StateTransitions: Unexpected exception:" + 
excep);
+                            continue;
+                        }
+                    }
+
+                    // Get new state, verify correct transition and exceptions 
occurred
+                    new_state = currentState(obj);
+                    if( expected_state == ERROR ){
+                        if( e == null ){
+                            printSituation();
+                            fail(ASSERTION_FAILED,
+                                 "StateTransitions: JDOUserException should 
have been thrown");
+                        } else {
+                            if( new_state != current_state ){
+                                printSituation();
+                                fail(ASSERTION_FAILED,
+                                     "StateTransitions: " + 
+                                     " JDOUserException properly thrown, but 
instance should remain in current state," +
+                                     "instance changed state to " + 
states[new_state]);
+                            }
+                        }
+                    }
+                    if( expected_state >= 0 && new_state != expected_state && 
+                        !((new_state == HOLLOW && expected_state == 
PERSISTENT_NONTRANSACTIONAL) ||
+                          (new_state == PERSISTENT_NONTRANSACTIONAL && 
expected_state == HOLLOW)) ) { 
+                        // status interrogation gives same values for 
PERSISTENT_NONTRANSACTIONAL and HOLLOW
+                        printSituation();
+                        fail(ASSERTION_FAILED,
+                             "StateTransitions: Invalid state transition to " +
+                             states[new_state] + ", new state should be " +
+                             states[expected_state]);
+                    }
+                    if( transaction.isActive() ) transaction.rollback();
+                } 
+                catch(Exception unexpected_exception) {
+                    printSituation();
+                    if (transaction.isActive()) 
+                        transaction.rollback();
+                    fail(ASSERTION_FAILED,
+                         "Unexpected exception caught in StateTransitions " + 
unexpected_exception);
+                }
+            }
+        }
+    }
+
+    /** */
+    void printSituation()
+    {
+        if (debug) {
+            logger.debug(" (" + scenario_string[scenario] +
+                         ", initial state=" + states[current_state] + 
+                         ", operation=" + operations[operation] + ")");
+        }
+    }
+
+    /** */
+    void applyOperation(int operation, StateTransitionObj stobj)
+    {
+        StateTransitionObj obj = (StateTransitionObj) stobj;
+        switch( operation ){
+        case MAKEPERSISTENT:
+        {
+            pm.makePersistent(obj);
+            break;
+        }
+        case DELETEPERSISTENT:
+        {
+            pm.deletePersistent(obj);
+            break;
+        }
+        case MAKETRANSACTIONAL:
+        {
+            pm.makeTransactional(obj);
+            break;
+        }
+        case MAKENONTRANSACTIONAL:
+        {
+            pm.makeNontransactional(obj);
+            break;
+        }
+        case MAKETRANSIENT:
+        {
+            pm.makeTransient(obj);
+            break;
+        }
+        case COMMITNORETAINVALUES:
+        {
+            pm.currentTransaction().commit();
+            break;
+        }
+        case COMMITRETAINVALUES:
+        {
+            pm.currentTransaction().commit();
+            break;
+        }
+        case ROLLBACKNORESTOREVALUES:
+        {
+            pm.currentTransaction().rollback();
+            break;
+        }
+        case ROLLBACKRESTOREVALUES:
+        {
+            pm.currentTransaction().rollback();
+            break;
+        }
+        case REFRESHDATASTORE:
+        {
+            pm.refresh(obj);
+            break;
+        }
+        case REFRESHOPTIMISTIC:
+        {
+            pm.refresh(obj);
+            break;
+        }
+        case EVICT:
+        {
+            pm.evict(obj);
+            break;
+        }
+        case READOUTSIDETX:
+        {
+            int val = obj.readField();
+            break;
+        }
+        case READOPTIMISTIC:
+        {
+            int val = obj.readField();
+            break;
+        }
+        case READDATASTORE:
+        {
+            int val = obj.readField();
+            break;
+        }
+        case WRITEOUTSIDETX:
+        {
+            obj.writeField(42);
+            break;
+        }
+        case WRITEINSIDETX:
+        {
+            obj.writeField(42);
+            break;
+        }
+        case RETRIEVEOUTSIDETX:
+        {
+            pm.retrieve(obj);
+            break;
+        }
+        case RETRIEVEINSIDETX:
+        {
+            pm.retrieve(obj);
+            break;             
+        }
+        default:
+        {
+            fail(ASSERTION_FAILED,
+                 "StateTransitions internal error, illegal operation " + 
operation);
+        }
+        }
+    }
+
+    /**
+     * Get an instance in the specified state.
+     */
+    private StateTransitionObj getInstanceInState(int state)
+    {
+        switch(state) {
+        case TRANSIENT:
+            return getTransientInstance();
+        case PERSISTENT_NEW:
+            return getPersistentNewInstance();
+        case PERSISTENT_CLEAN:
+            return getPersistentCleanInstance();
+        case PERSISTENT_DIRTY:
+            return getPersistentDirtyInstance();
+        case HOLLOW:
+            return getHollowInstance();
+        case TRANSIENT_CLEAN:
+            return getTransientCleanInstance();
+        case TRANSIENT_DIRTY:
+            return getTransientDirtyInstance();
+        case PERSISTENT_NEW_DELETED:
+            return getPersistentNewDeletedInstance();
+        case PERSISTENT_DELETED:
+            return getPersistentDeletedInstance();
+        case PERSISTENT_NONTRANSACTIONAL:
+            return getPersistentNontransactionalInstance();
+        default:
+        {
+            return null;
+        }
+        }
+    }
+
+    /** */
+    private StateTransitionObj getTransientInstance()
+    {
+        StateTransitionObj obj = new StateTransitionObj(23);
+        int curr = currentState(obj);
+        if( curr != TRANSIENT ) {
+            if (debug) {
+                logger.debug("StateTransitions: Unable to create transient 
instance, state is " + 
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return obj;
+    }
+
+    /** */
+    private StateTransitionObj getPersistentNewInstance()
+    {
+        StateTransitionObj obj = getTransientInstance();
+        if( obj == null ) return null;
+        pm.makePersistent(obj); // should transition to persistent-new
+        int curr = currentState(obj);
+        if( curr != PERSISTENT_NEW ) {
+            if (debug) {
+                logger.debug("StateTransitions: Unable to create 
persistent-new instance" +
+                             " from transient instance via makePersistent(), 
state is " +
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return obj;
+    }
+    
+    /** */
+    public StateTransitionObj getPersistentCleanInstance()
+    {
+        StateTransitionObj obj = getHollowInstance();
+        if( obj == null ) return null;
+        StateTransitionObj sto = (StateTransitionObj) obj;
+        int val = sto.readField();
+        int curr = currentState(sto);
+        if( curr != PERSISTENT_CLEAN ) {
+            if (debug) {
+                logger.debug("StateTransition: Unable to create 
persistent-clean instance" +
+                             " from a hollow instance by reading a field, 
state is " +
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return obj;
+    }
+    
+    /** */
+    public StateTransitionObj getPersistentDirtyInstance()
+    {
+        StateTransitionObj obj = getHollowInstance();
+        if( obj == null ) return null;
+        StateTransitionObj pcobj = (StateTransitionObj) obj;
+        pcobj.writeField(23);
+        int curr = currentState(obj);
+        if( curr != PERSISTENT_DIRTY ) {
+            if (debug) {
+                logger.debug("StateTransition: Unable to create 
persistent-dirty instance" +
+                             " from a hollow instance by writing a field, 
state is " +
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return obj;
+    }
+
+    /** */
+    public StateTransitionObj getHollowInstance()
+    {
+        Extent extent = pm.getExtent(StateTransitionObj.class, false);
+        Iterator iter = extent.iterator();
+        if( !iter.hasNext() ){
+            if (debug)
+                logger.debug("Extent for StateTransitionObj should not be 
empty");
+            return null;
+        }
+        StateTransitionObj obj = (StateTransitionObj) iter.next();
+        
+        transaction.setRetainValues(false);
+        if ( !transaction.isActive() )
+            transaction.begin();
+        if( !transaction.isActive() )
+            if (debug)
+                logger.debug("getHollowInstance: Transaction should be active, 
but it is not");
+               
+        transaction.commit(); // This should put the instance in the HOLLOW 
state
+
+        if( scenario != NO_TX ){
+            if( operation == COMMITNORETAINVALUES )
+                transaction.setRetainValues(false);
+            if( operation == COMMITRETAINVALUES )
+                transaction.setRetainValues(true);
+            if( operation == ROLLBACKNORESTOREVALUES )
+                transaction.setRestoreValues(false);
+            if( operation == ROLLBACKRESTOREVALUES )
+                transaction.setRestoreValues(true);
+
+            transaction.setOptimistic(scenario == OPTIMISTIC_TX);
+            transaction.begin();
+            if( !transaction.isActive() )
+                if (debug)
+                    logger.debug("getHollowInstance: Transaction should be 
active, but it is not");
+        }
+
+        int curr = currentState(obj);
+        if( curr != HOLLOW && curr != PERSISTENT_NONTRANSACTIONAL ){
+            if (debug) {
+                logger.debug("StateTransition: Attempt to get hollow instance 
via accessing extent failed, state is " +
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return obj;
+    }
+    
+    /** */
+    public StateTransitionObj getTransientCleanInstance()
+    {
+        StateTransitionObj obj = getTransientInstance();
+        if( obj == null ) return null;
+        pm.makeTransactional(obj);
+        int curr = currentState(obj);
+        if( curr != TRANSIENT_CLEAN ) {
+            if (debug) {
+                logger.debug("StateTransition: Unable to create 
transient-clean instance" +
+                             " from a transient instance via 
makeTransactional(), state is " +
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return obj;
+    }
+
+    /** */
+    public StateTransitionObj getTransientDirtyInstance()
+    {
+        StateTransitionObj obj = getTransientCleanInstance();
+        if( obj == null ) return null;
+        StateTransitionObj pcobj = (StateTransitionObj) obj;
+        pcobj.writeField(23);
+        int curr = currentState(obj);
+        if( curr != TRANSIENT_DIRTY ) { 
+            if (debug) {
+                logger.debug("StateTransition: Unable to create 
transient-dirty instance" +
+                             " from a transient-clean instance via modifying a 
field, state is " +
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return obj;
+    }
+
+    /** */
+    public StateTransitionObj getPersistentNewDeletedInstance()
+    {
+        StateTransitionObj obj = getPersistentNewInstance();
+        if( obj == null ) return null;
+        pm.deletePersistent(obj);   // should transition to 
persistent-new-deleted
+        int curr = currentState(obj);
+        if( curr != PERSISTENT_NEW_DELETED) { 
+            if (debug) {
+                logger.debug("StateTransition: Unable to create 
persistent-new-deleted instance" +
+                             " from a persistent-new instance via 
deletePersistent, state is " +
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return obj;
+    }
+    
+    /** */
+    public StateTransitionObj getPersistentDeletedInstance()
+    {
+        StateTransitionObj obj = getHollowInstance();
+        if( obj == null ) return null;
+        pm.deletePersistent(obj);
+        int curr = currentState(obj);
+        if( curr != PERSISTENT_DELETED ) { 
+            if (debug) {
+                logger.debug("StateTransition: Unable to create 
persistent-deleted instance" +
+                             " from a persistent instance via 
deletePersistent(), state is " +
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return obj;
+    }
+
+    /** */
+    public StateTransitionObj getPersistentNontransactionalInstance()
+    {
+        StateTransitionObj obj = getHollowInstance();
+        if( obj == null ) return null;
+        pm.makeNontransactional(obj);
+        int curr = currentState(obj);
+        if( curr != PERSISTENT_NONTRANSACTIONAL && curr != HOLLOW ) { 
+            if (debug) {
+                logger.debug("StateTransition: Unable to create 
persistent-nontransactional instance" +
+                             " from a persistent-clean instance via 
makeNontransactional(), state is " +
+                             states[curr]);
+            }
+            printSituation();
+            return null;
+        }
+        return null;
+    }
+
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/StateTransitions.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateCommit.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateCommit.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateCommit.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateCommit.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ 
+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;
+
+/**
+ *<B>Title:</B> Test Transient Transactional Commit
+ *<BR>
+ *<B>Keywords:</B> lifecycle transienttransactional commit
+ *<BR>
+ *<B>Assertion IDs:</B> A5.1-3
+ *<BR>
+ *<B>Assertion Description: </B>
+ If <code>TransientTransactional</code> is supported, a transient 
transactional instance
+ will have its state preserved when its associated transaction commits.
+*/
+
+
+public class TransientTransactionalStateCommit extends JDO_Test {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertion A5.1-3 (TransientTransactionalStateCommit) failed: ";
+
+    private static final int CLEAN_VALUE = 12;
+    private static final int DIRTY_VALUE = 123;
+    
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+        BatchTestRunner.run(TransientTransactionalStateCommit.class);
+    }
+
+    /** */
+    public void test() {
+        if (!isTransientTransactionalSupported()) {
+            logger.debug("Transient transactional instances are not 
supported");
+        }
+        else {
+            pm = getPM();
+
+            StateTransitionObj obj = getTransientInstance();
+
+            pm.currentTransaction().begin();
+
+            makeTransientDirty(obj);
+
+            int beforeValue=obj.readField();
+            pm.currentTransaction().commit();
+            int afterValue=obj.readField();
+            if (beforeValue!=afterValue)
+            {
+                fail(ASSERTION_FAILED,
+                     "Field value incorrect after commit. Expected: " +
+                     beforeValue + " Found: " + afterValue);
+            }
+        }
+    }
+
+    protected StateTransitionObj getTransientInstance() {
+        StateTransitionObj obj = new StateTransitionObj(CLEAN_VALUE);
+        int curr = currentState(obj);
+        if( curr != TRANSIENT ){
+            fail(ASSERTION_FAILED,
+                 "Unable to create transient instance, state is " +
+                 states[curr]);
+        }
+        return obj;
+    }
+    
+    protected void makeTransientClean(StateTransitionObj obj) {
+        if( obj == null ) return;
+        pm.makeTransactional(obj);
+        int curr = currentState(obj);
+        if( curr != TRANSIENT_CLEAN ){
+            fail(ASSERTION_FAILED,
+                 "Unable to create transient-clean instance " +
+                 "from a transient instance via makeTransactional(), state is 
" +
+                 states[curr]);
+        }
+    }
+
+    protected void makeTransientDirty(StateTransitionObj obj) {
+        if( obj == null ) return;
+        makeTransientClean(obj);
+        obj.writeField(DIRTY_VALUE);
+        int curr = currentState(obj);
+        if( curr != TRANSIENT_DIRTY ){
+            fail(ASSERTION_FAILED,
+                 "Unable to create transient-dirty instance " +
+                 "from a transient-clean instance via modifying a field, state 
is " +
+                 states[curr]);
+        }
+    }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateCommit.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateRollback.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateRollback.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateRollback.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateRollback.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+ 
+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;
+
+/**
+ *<B>Title:</B> Test Transient Transactional Rollback
+ *<BR>
+ *<B>Keywords:</B> lifecycle transienttransactional rollback
+ *<BR>
+ *<B>Assertion IDs:</B> A5.1-4
+ *<B>Assertion Description: </B>
+ If <code>TransientTransactional</code> is supported, a transient 
transactional instance
+ will have its state restored to its state prior to becoming transactional when
+ its associated transaction aborts or on rollback.
+ */
+
+public class TransientTransactionalStateRollback extends JDO_Test {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertion A5.1-4 (TransientTransactionalStateRollback) failed: ";
+    
+    private static final int CLEAN_VALUE = 12;
+    private static final int DIRTY_VALUE = 123;
+    
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+        BatchTestRunner.run(TransientTransactionalStateRollback.class);
+    }
+    
+    /** */
+    public void test() {
+        if (!isTransientTransactionalSupported()) {
+            logger.debug("Transient transactional instances are not 
supported");
+        }
+        else {
+            pm = getPM();
+            
+            // Get transient instance and read field value
+            StateTransitionObj obj = getTransientInstance();
+
+            int beforeValue=obj.readField();
+
+            // Start transaction
+            Transaction tx = pm.currentTransaction();
+            tx.begin();
+
+            // Get transient dirty instance
+            makeTransientDirty(obj);
+
+            // Rollback
+            tx.rollback();
+            int curr = currentState(obj);
+            if( curr != TRANSIENT_CLEAN ){
+                fail(ASSERTION_FAILED,
+                     "StateTransition: Unable to create transient-clean 
instance " +
+                     "from a transient-dirty instance via tx.rollback(), state 
is " + states[curr]);
+            }
+
+            // Check that field value has been rolled back
+            int afterValue=obj.readField();
+            if (beforeValue!=afterValue)
+            {
+                fail(ASSERTION_FAILED,
+                     "Field value incorrect after rollback. Expected: 
"+beforeValue+" Found: "+afterValue);
+            }
+        }
+    }
+
+    protected StateTransitionObj getTransientInstance() {
+        StateTransitionObj obj = new StateTransitionObj(CLEAN_VALUE);
+        int curr = currentState(obj);
+        if( curr != TRANSIENT ){
+            fail(ASSERTION_FAILED,
+                 "Unable to create transient instance, state is " + 
states[curr]);
+        }
+        return obj;
+    }
+
+    protected void makeTransientClean(StateTransitionObj obj) {
+        if( obj == null ) return;
+        pm.makeTransactional(obj);
+        int curr = currentState(obj);
+        if( curr != TRANSIENT_CLEAN ){
+            fail(ASSERTION_FAILED,
+                 "Unable to create transient-clean instance " +
+                 "from a transient instance via makeTransactional(), state is 
" + states[curr]);
+        }
+    }
+
+    protected void makeTransientDirty(StateTransitionObj obj) {
+        if( obj == null ) return;
+        makeTransientClean(obj);
+        obj.writeField(DIRTY_VALUE);
+        int curr = currentState(obj);
+        if( curr != TRANSIENT_DIRTY ){
+            fail(ASSERTION_FAILED,
+                 "Unable to create transient-dirty instance " +
+                 "from a transient-clean instance via modifying a field, state 
is " + states[curr]);
+        }
+    }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/TransientTransactionalStateRollback.java
------------------------------------------------------------------------------
    svn:executable = *

Added: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/nontransactional/ModificationOfNontransactionalInstanceOutsideTransaction.java
URL: 
http://svn.apache.org/viewcvs/incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/nontransactional/ModificationOfNontransactionalInstanceOutsideTransaction.java?view=auto&rev=160090
==============================================================================
--- 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/nontransactional/ModificationOfNontransactionalInstanceOutsideTransaction.java
 (added)
+++ 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/nontransactional/ModificationOfNontransactionalInstanceOutsideTransaction.java
 Mon Apr  4 12:41:23 2005
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at 
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software 
+ * distributed under the License is distributed on an "AS IS" BASIS, 
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+ * See the License for the specific language governing permissions and 
+ * limitations under the License.
+ */
+
+package org.apache.jdo.tck.lifecycle.nontransactional;
+
+import java.util.Iterator;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.Extent;
+
+import org.apache.jdo.tck.JDO_Test;
+import org.apache.jdo.tck.pc.lifecycle.StateTransitionObj;
+import org.apache.jdo.tck.util.BatchTestRunner;
+
+/**
+ *<B>Title:</B> Modification of Nontransactional Persistent Instance Outside a 
Transaction
+ *<BR>
+ *<B>Keywords:</B> nontransactionalwrite
+ *<BR>
+ *<B>Assertion ID:</B> A5.6-9.
+ *<BR>
+ *<B>Assertion Description: </B>
+ * With <code>NontransactionalWrite</code> set to <code>true</code>,
+ * modification of nontransactional persistent instances is permitted outside
+ * a transaction.  The changes do not participate in any subsequent 
transaction.
+ */
+
+public class ModificationOfNontransactionalInstanceOutsideTransaction extends 
JDO_Test {
+
+    /** */
+    private static final String ASSERTION_FAILED = 
+        "Assertion A5.6-9 
(ModificationOfNontransactionalInstanceOutsideTransaction) failed: ";
+    
+    /**
+     * The <code>main</code> is called when the class
+     * is directly executed from the command line.
+     * @param args The arguments passed to the program.
+     */
+    public static void main(String[] args) {
+        
BatchTestRunner.run(ModificationOfNontransactionalInstanceOutsideTransaction.class);
+    }
+    
+    /** 
+     * The pc instance, set by method createAndModifyInstance. 
+     */
+    private StateTransitionObj object;
+
+    /** 
+     * The ObjectId of the pc instance, set by method
+     * createAndModifyInstance. 
+     */ 
+    private Object oid;
+
+    /**
+     * The original value of the int field of the pc instance, 
+     * set by method createAndModifyInstance. 
+     */
+    private int originalValue;
+
+    /** */
+    public void testDifferentPM() {
+        if (!isNontransactionalWriteSupported()) {
+            printUnsupportedOptionalFeatureNotTested(
+                "NontransactionalWrite", "testDifferentPM");
+        }
+        else {
+            pm = getPM();
+            createAndModifyInstance();
+
+            int value=object.readField();
+            if (value!=999){
+                fail(ASSERTION_FAILED,
+                     "Unable to write value to field with 
setNontransactionalWrite==true");
+            }
+
+            // begin new transaction, read instance from datastore and 
+            // verify that old value is still there
+            PersistenceManager pm2 = null;
+            try {
+                pm2 = getPMF().getPersistenceManager();
+                pm2.currentTransaction().begin();
+                StateTransitionObj object2 =
+                    (StateTransitionObj)pm2.getObjectById(oid,true);
+                if (object2 == null){
+                    fail(ASSERTION_FAILED, 
+                         "Failed to read instance from datastore via 
pm.getObjectById(...)");
+                }
+                
+                int value2 = object2.readField();
+                if (value2 != originalValue){
+                    fail(ASSERTION_FAILED, 
+                         "Value has been changed with 
setNontransactionalWrite==true. " + 
+                         "New value is " + value2 + " ... Old value was " + 
originalValue);
+                }
+                pm2.currentTransaction().commit();
+            }
+            finally {
+                if ((pm2 != null) && !pm2.isClosed()) {
+                    if (pm2.currentTransaction().isActive())
+                        pm2.currentTransaction().rollback();
+                    pm2.close();
+                }
+            }
+        }
+    }
+    
+    /** */
+    public void testSameInstance() {
+        if (!isNontransactionalWriteSupported()) {
+            printUnsupportedOptionalFeatureNotTested(
+                "NontransactionalWrite", "testDifferentPM");
+        }
+        else {
+            pm = getPM();
+            createAndModifyInstance();
+
+            // use the object in a new datastore transaction
+            pm.currentTransaction().setOptimistic(false);
+            pm.currentTransaction().begin();
+            int value = object.readField();
+            if (value != originalValue){
+                fail(ASSERTION_FAILED, 
+                     "Value has been changed with 
setNontransactionalWrite==true. " + 
+                     "New value is " + value + " ... Old value was " + 
originalValue);
+            }
+            pm.currentTransaction().commit();
+        }
+    }
+
+    /** */
+    public void testIterateExtent() {
+        if (!isNontransactionalWriteSupported()) {
+            printUnsupportedOptionalFeatureNotTested(
+                "NontransactionalWrite", "testDifferentPM");
+        }
+        else {
+            pm = getPM();
+            createAndModifyInstance();
+
+            // iterate the extent and use the object in a new datastore 
transaction
+            pm.currentTransaction().setOptimistic(false);
+            pm.currentTransaction().begin();
+            Extent e = pm.getExtent(StateTransitionObj.class, false);
+            for (Iterator i = e.iterator(); i.hasNext();) {
+                StateTransitionObj next = (StateTransitionObj)i.next();
+                if (oid.equals(pm.getObjectId(next))) {
+                    // found instance
+                    int value = next.readField();
+                    if (value != originalValue){
+                        fail(ASSERTION_FAILED, 
+                             "Value has been changed with 
setNontransactionalWrite==true. " + 
+                             "New value is " + value + " ... Old value was " + 
originalValue);
+                    }
+                }
+            }
+            pm.currentTransaction().commit();
+        }
+    }
+
+    /** */
+    private void createAndModifyInstance() {
+        pm.currentTransaction().begin();
+        // create and save the pc instance
+        object = getPersistentNewInstance();
+        // save the ObjectId
+        oid = pm.getObjectId(object);
+        // save the value of the int field
+        originalValue = object.readField();
+        pm.currentTransaction().commit();
+        
+        // change field outside of transaction
+        pm.currentTransaction().setNontransactionalWrite(true);
+        object.writeField(999);
+    }
+
+    /** */
+    private StateTransitionObj getPersistentNewInstance() {
+        StateTransitionObj obj = new StateTransitionObj();
+        pm.makePersistent(obj); // obj should transition to PERSISTENT_NEW
+        int curr = currentState(obj);
+        if (curr != PERSISTENT_NEW) {
+            fail(ASSERTION_FAILED,
+                 "Unable to create persistent-new instance " +
+                 "from transient instance via makePersistent(), state is " + 
+                 getStateOfInstance(obj));
+        }
+        return obj;
+    }
+}

Propchange: 
incubator/jdo/trunk/tck20/test/java/org/apache/jdo/tck/lifecycle/nontransactional/ModificationOfNontransactionalInstanceOutsideTransaction.java
------------------------------------------------------------------------------
    svn:executable = *


Reply via email to