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 = *