You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by mc...@apache.org on 2007/01/14 19:05:26 UTC
svn commit: r496105 [2/3] - in
/db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/lifecycle:
StateTransitions.java StateTransitionsReturnedObjects.java
Modified: db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/lifecycle/StateTransitions.java
URL: http://svn.apache.org/viewvc/db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/lifecycle/StateTransitions.java?view=diff&rev=496105&r1=496104&r2=496105
==============================================================================
--- db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/lifecycle/StateTransitions.java (original)
+++ db/jdo/trunk/tck20/src/java/org/apache/jdo/tck/lifecycle/StateTransitions.java Sun Jan 14 10:05:25 2007
@@ -1,1074 +1,1074 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectOutputStream;
-import java.util.Iterator;
-
-import javax.jdo.Extent;
-import javax.jdo.JDOFatalException;
-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 int DETACHALLONCOMMIT = 19;
- private static final int DETACHCOPYOUTSIDETXNTRTRU = 20;
- private static final int DETACHCOPYOUTSIDETXNTRFLS = 21;
- private static final int DETACHCOPYINSIDEDATASTORETX = 22;
- private static final int DETACHCOPYINSIDEOPTIMISTICTX = 23;
- private static final int SERIALIZEOUTSIDETX = 24;
- private static final int SERIALIZEDATASTORE = 25;
- private static final int SERIALIZEOPTIMISTIC = 26;
-
- private static final int NUM_OPERATIONS = 27;
-
- 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",
- "commit, detachAllOnCommit=true",
- "detachCopy outside tx with NontransactionalRead=true",
- "detachCopy outside tx with NontransactionalRead=false",
- "detachCopy with active datastore tx",
- "detachCopy with active optimistic tx",
- "serialize outside tx",
- "serialize with active datastore tx",
- "serialize with active optimistic tx"
- };
-
- /**
- * 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;
- private static final int UNSPECIFIED = -5;
-
- /**
- * State transitions
- */
- public static final int[][] transitions = { // [operation] [current state] = new state
- // TRANSIENT, PERSISTENT_NEW, PERSISTENT_CLEAN,
- // PERSISTENT_DIRTY, HOLLOW, TRANSIENT_CLEAN,
- // TRANSIENT_DIRTY, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
- // PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL_DIRTY, DETACHED_CLEAN,
- // DETACHED_DIRTY
-
- // makePersistent
- { PERSISTENT_NEW, UNCHANGED, UNCHANGED,
- UNCHANGED, UNCHANGED, PERSISTENT_NEW,
- PERSISTENT_NEW, UNCHANGED, UNCHANGED,
- UNCHANGED, UNCHANGED, DETACHED_CLEAN,
- DETACHED_DIRTY},
-
- // deletePersistent
- { ERROR, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
- PERSISTENT_DELETED, PERSISTENT_DELETED, ERROR,
- ERROR, UNCHANGED, UNCHANGED,
- PERSISTENT_DELETED, PERSISTENT_DELETED, ERROR,
- ERROR},
-
- // makeTransactional
- { TRANSIENT_CLEAN, UNCHANGED, UNCHANGED,
- UNCHANGED, PERSISTENT_CLEAN, UNCHANGED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- PERSISTENT_CLEAN, PERSISTENT_DIRTY, ERROR,
- ERROR},
-
- // makeNontransactional
- { ERROR, ERROR, PERSISTENT_NONTRANSACTIONAL,
- ERROR, UNCHANGED, TRANSIENT,
- ERROR, ERROR, ERROR,
- UNCHANGED, UNCHANGED, ERROR,
- ERROR},
-
- // makeTransient
- { UNCHANGED, ERROR, TRANSIENT,
- ERROR, TRANSIENT, UNCHANGED,
- UNCHANGED, ERROR, ERROR,
- TRANSIENT, ERROR, ERROR,
- ERROR},
-
- // commit, retainValues = false
- { UNCHANGED, HOLLOW, HOLLOW,
- HOLLOW, UNCHANGED, UNCHANGED,
- TRANSIENT_CLEAN, TRANSIENT, TRANSIENT,
- UNCHANGED, HOLLOW, UNCHANGED,
- UNCHANGED},
-
- // commit, retainValues = true
- { UNCHANGED, PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL,
- PERSISTENT_NONTRANSACTIONAL, UNCHANGED, UNCHANGED,
- TRANSIENT_CLEAN, TRANSIENT, TRANSIENT,
- UNCHANGED, PERSISTENT_NONTRANSACTIONAL, UNCHANGED,
- UNCHANGED},
-
- // TRANSIENT, PERSISTENT_NEW, PERSISTENT_CLEAN,
- // PERSISTENT_DIRTY, HOLLOW, TRANSIENT_CLEAN,
- // TRANSIENT_DIRTY, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
- // PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL_DIRTY, DETACHED_CLEAN,
- // DETACHED_DIRTY
-
- // rollback, restoreValues = false
- { UNCHANGED, TRANSIENT, HOLLOW,
- HOLLOW, UNCHANGED, UNCHANGED,
- TRANSIENT_CLEAN, TRANSIENT, HOLLOW,
- UNCHANGED, HOLLOW, UNCHANGED,
- UNCHANGED},
-
- // rollback, restoreValues = true
- { UNCHANGED, TRANSIENT, PERSISTENT_NONTRANSACTIONAL,
- PERSISTENT_NONTRANSACTIONAL, UNCHANGED, UNCHANGED,
- TRANSIENT_CLEAN, TRANSIENT, PERSISTENT_NONTRANSACTIONAL,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED},
-
- // refresh with active datastore transaction
- { UNCHANGED, UNCHANGED, UNCHANGED,
- PERSISTENT_CLEAN, UNCHANGED, UNCHANGED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, PERSISTENT_NONTRANSACTIONAL, UNCHANGED,
- UNCHANGED},
-
- // refresh with active optimistic transaction
- { UNCHANGED, UNCHANGED, UNCHANGED,
- PERSISTENT_NONTRANSACTIONAL, UNCHANGED, UNCHANGED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, PERSISTENT_NONTRANSACTIONAL, UNCHANGED,
- UNCHANGED},
-
- // evict
- { NOT_APPLICABLE, UNCHANGED, HOLLOW,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- HOLLOW, HOLLOW, UNCHANGED,
- UNCHANGED},
-
- // read field outside transaction
- { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE,
- IMPOSSIBLE, PERSISTENT_NONTRANSACTIONAL, IMPOSSIBLE,
- IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED},
-
- // read field with active optimistic transaction
- { UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, PERSISTENT_NONTRANSACTIONAL, UNCHANGED,
- UNCHANGED, UNSPECIFIED, UNSPECIFIED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED},
-
- // TRANSIENT, PERSISTENT_NEW, PERSISTENT_CLEAN,
- // PERSISTENT_DIRTY, HOLLOW, TRANSIENT_CLEAN,
- // TRANSIENT_DIRTY, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
- // PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL_DIRTY, DETACHED_CLEAN,
- // DETACHED_DIRTY
-
- // read field with active datastore transaction
- { UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, PERSISTENT_CLEAN, UNCHANGED,
- UNCHANGED, UNSPECIFIED, UNSPECIFIED,
- PERSISTENT_CLEAN, UNCHANGED, UNCHANGED,
- UNCHANGED},
-
- // write field outside transaction
- { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE,
- IMPOSSIBLE, PERSISTENT_NONTRANSACTIONAL, IMPOSSIBLE,
- IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
- UNCHANGED, UNCHANGED, DETACHED_DIRTY,
- UNCHANGED},
-
- // write field with active transaction
- { UNCHANGED, UNCHANGED, PERSISTENT_DIRTY,
- UNCHANGED, PERSISTENT_DIRTY, TRANSIENT_DIRTY,
- UNCHANGED, ERROR, ERROR,
- PERSISTENT_DIRTY, UNCHANGED, DETACHED_DIRTY,
- UNCHANGED},
-
- // retrieve outside transaction
- { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE,
- IMPOSSIBLE, PERSISTENT_NONTRANSACTIONAL, IMPOSSIBLE,
- IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED},
-
- // retrieve with active transaction
- { UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, PERSISTENT_CLEAN, UNCHANGED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- PERSISTENT_CLEAN, UNCHANGED, UNCHANGED,
- UNCHANGED},
-
- // commit, detachAllOnCommit = true
- { UNCHANGED, DETACHED_CLEAN, DETACHED_CLEAN,
- DETACHED_CLEAN, DETACHED_CLEAN, UNCHANGED,
- TRANSIENT_CLEAN, TRANSIENT, TRANSIENT,
- DETACHED_CLEAN, DETACHED_CLEAN, UNCHANGED,
- UNCHANGED},
-
- // TRANSIENT, PERSISTENT_NEW, PERSISTENT_CLEAN,
- // PERSISTENT_DIRTY, HOLLOW, TRANSIENT_CLEAN,
- // TRANSIENT_DIRTY, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
- // PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL_DIRTY, DETACHED_CLEAN,
- // DETACHED_DIRTY
-
- // detachCopy outside tx with NontransactionalRead=true
- { ERROR, IMPOSSIBLE, IMPOSSIBLE,
- IMPOSSIBLE, PERSISTENT_NONTRANSACTIONAL, ERROR,
- IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
- UNCHANGED, UNSPECIFIED, UNCHANGED,
- UNSPECIFIED},
-
- // detachCopy outside tx with NontransactionalRead=false
- { ERROR, IMPOSSIBLE, IMPOSSIBLE,
- IMPOSSIBLE, ERROR, ERROR,
- IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
- ERROR, ERROR, ERROR,
- ERROR},
-
- // detachCopy with active datastore tx
- { PERSISTENT_NEW, UNCHANGED, UNCHANGED,
- UNCHANGED, PERSISTENT_CLEAN, PERSISTENT_NEW,
- PERSISTENT_NEW, ERROR, ERROR,
- UNCHANGED, IMPOSSIBLE, UNCHANGED,
- UNCHANGED},
-
- // detachCopy with active optimistic tx
- { PERSISTENT_NEW, UNCHANGED, UNCHANGED,
- UNCHANGED, PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NEW,
- PERSISTENT_NEW, ERROR, ERROR,
- UNCHANGED, IMPOSSIBLE, UNCHANGED,
- UNCHANGED},
-
- // serialize outside tx
- { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE,
- IMPOSSIBLE, UNCHANGED, IMPOSSIBLE,
- IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED},
-
- // serialize with active datastore tx
- { UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, PERSISTENT_CLEAN, UNCHANGED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- PERSISTENT_CLEAN, UNCHANGED, UNCHANGED,
- UNCHANGED},
-
- // serialize with active optimistic tx
- { UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED, UNCHANGED, UNCHANGED,
- UNCHANGED},
- };
-
- 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
- { true, true, false }, // commit, DetachAllOnCommit = true
- { false, false, true }, // detachCopy outside tx with NonTransactionaRead=true
- { false, false, true }, // detachCopy outside tx with NonTransactionaRead=false
- { true, false, false }, // detachCopy with active datastore tx
- { false, true, false }, // detachCopy with active optimistic tx
- { false, false, true }, // serialize outside tx
- { true, false, false }, // serialize with active datastore tx
- { false, true, false } // serialize with active optimistic tx
- };
-
- /**
- * @see JDO_Test#localSetUp()
- */
- protected void localSetUp() {
- pm = getPM();
- addTearDownClass(StateTransitionObj.class);
- generatePersistentInstances();
- }
-
- public void test() {
- scenario = DATASTORE_TX;
- checkTransitions();
-
- if( isOptimisticSupported() ){
- scenario = OPTIMISTIC_TX;
- checkTransitions();
- }
-
- scenario = NO_TX;
- checkTransitions();
- failOnError();
- }
-
- /** */
- 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;
- }
-
- /** */
- public void prepareTransactionAndJDOSettings(Transaction transaction) {
- if( scenario != NO_TX ) {
- transaction.setNontransactionalRead(false);
- transaction.setNontransactionalWrite(false);
-
- if( operation == COMMITNORETAINVALUES )
- transaction.setRetainValues(false);
- if( operation == COMMITRETAINVALUES )
- transaction.setRetainValues(true);
- if( operation == ROLLBACKNORESTOREVALUES )
- transaction.setRestoreValues(false);
- if( operation == ROLLBACKRESTOREVALUES )
- transaction.setRestoreValues(true);
- if( operation == DETACHALLONCOMMIT )
- pm.setDetachAllOnCommit(true);
- else
- pm.setDetachAllOnCommit(false);
-
- transaction.setOptimistic(scenario == OPTIMISTIC_TX);
- transaction.begin();
- if( !transaction.isActive() )
- if (debug)
- logger.debug("StateTransitions: Transaction should be active, but it is not");
- } else {
- if( operation == READOUTSIDETX ||
- operation == RETRIEVEOUTSIDETX ||
- operation == DETACHCOPYOUTSIDETXNTRTRU ||
- operation == SERIALIZEOUTSIDETX ) {
- transaction.setNontransactionalRead(true);
- }
- if( operation == WRITEOUTSIDETX ||
- current_state == PERSISTENT_NONTRANSACTIONAL_DIRTY) {
- transaction.setNontransactionalWrite(true);
- }
- }
- }
-
- /** */
- 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 ||
- operation == RETRIEVEOUTSIDETX ||
- operation == DETACHCOPYOUTSIDETXNTRTRU ||
- operation == SERIALIZEOUTSIDETX) &&
- !isNontransactionalReadSupported() ) continue;
- if( operation == WRITEOUTSIDETX && !isNontransactionalWriteSupported() ) continue;
- if( operation == COMMITRETAINVALUES && !isRetainValuesSupported() ) continue;
- if( operation == MAKENONTRANSACTIONAL &&
- !(isNontransactionalReadSupported() || isNontransactionalWriteSupported()) )
- continue;
- int NUM_JDO1_STATES = NUM_STATES - 2; // JDO1 is tested so far here.
- for( current_state = 0; current_state < NUM_JDO1_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
- if( current_state == PERSISTENT_NONTRANSACTIONAL_DIRTY &&
- !isNontransactionalWriteSupported() )
- continue;
-
- expected_state = transitions[operation][current_state];
- if( expected_state == IMPOSSIBLE ) continue;
- if( expected_state == NOT_APPLICABLE ) continue;
- if( expected_state == UNSPECIFIED ) 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();
- }
-
- prepareTransactionAndJDOSettings(transaction);
-
- printSituation();
-
- 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 {
- appendMessage(ASSERTION_FAILED + NL +
- "StateTransitions: " +
- scenario_string[scenario] +
- "; current state " + states[current_state] + NL +
- operations[operation] +
- "; unexpected exception:" + excep);
- continue;
- }
- }
-
- // Get new state, verify correct transition and exceptions occurred
- new_state = currentState(obj);
- if( expected_state == ERROR ){
- if( e == null ){
- appendMessage(ASSERTION_FAILED + NL +
- "StateTransitions: " +
- scenario_string[scenario] +
- "; current state " + states[current_state] + NL +
- operations[operation] +
- "; JDOUserException should have been thrown");
- } else {
- if( new_state != current_state ){
- appendMessage(ASSERTION_FAILED + NL +
- "StateTransitions: " +
- scenario_string[scenario] +
- "; current state " + states[current_state] + NL +
- operations[operation] +
- "; JDOUserException properly thrown, but instance should remain in current state," +
- "instance changed state to " + states[new_state]);
- }
- }
- }
- if( !compareStates(new_state, expected_state) ) {
- appendMessage(ASSERTION_FAILED + NL +
- "StateTransitions: " +
- scenario_string[scenario] +
- "; current state " + states[current_state] + NL +
- operations[operation] +
- " transitioned instance to invalid state " + states[new_state] +
- "; expected state " + states[expected_state]);
- }
- if( transaction.isActive() ) transaction.rollback();
- }
- catch(Exception unexpected_exception) {
- if (transaction.isActive())
- transaction.rollback();
- appendMessage(ASSERTION_FAILED + NL +
- "StateTransitions: " +
- scenario_string[scenario] +
- "; current state " + states[current_state] + NL +
- operations[operation] +
- "; unexpected exception caught: " + 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:
- {
- obj.readField();
- break;
- }
- case READOPTIMISTIC:
- {
- obj.readField();
- break;
- }
- case READDATASTORE:
- {
- 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;
- }
- case DETACHALLONCOMMIT:
- {
- pm.currentTransaction().commit();
- break;
- }
- case DETACHCOPYOUTSIDETXNTRTRU:
- {
- pm.detachCopy(obj);
- break;
- }
- case DETACHCOPYOUTSIDETXNTRFLS:
- {
- pm.detachCopy(obj);
- break;
- }
- case DETACHCOPYINSIDEDATASTORETX:
- {
- pm.detachCopy(obj);
- break;
- }
- case DETACHCOPYINSIDEOPTIMISTICTX:
- {
- pm.detachCopy(obj);
- break;
- }
- case SERIALIZEOUTSIDETX:
- {
- ObjectOutputStream oos = null;
- try {
- oos = new ObjectOutputStream(new ByteArrayOutputStream());
- oos.writeObject(obj);
- } catch (IOException e) {
- throw new JDOFatalException(e.getMessage(), e);
- } finally {
- if (oos != null) {
- try {
- oos.close();
- } catch (IOException e) {
- throw new JDOFatalException(e.getMessage(), e);
- }
- }
- }
- break;
- }
- case SERIALIZEDATASTORE:
- case SERIALIZEOPTIMISTIC:
- {
- ObjectOutputStream oos = null;
- try {
- oos = new ObjectOutputStream(new ByteArrayOutputStream());
- oos.writeObject(obj);
- } catch (IOException e) {
- throw new JDOFatalException(e.getMessage(), e);
- } finally {
- if (oos != null) {
- try {
- oos.close();
- } catch (IOException e) {
- throw new JDOFatalException(e.getMessage(), e);
- }
- }
- }
- break;
- }
- default:
- {
- appendMessage(ASSERTION_FAILED + NL +
- "StateTransitions: " +
- scenario_string[scenario] +
- "; internal error, illegal operation: " + operation);
- }
- }
- }
-
- /**
- * Get an instance in the specified state.
- */
- public 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();
- case PERSISTENT_NONTRANSACTIONAL_DIRTY:
- return getPersistentNontransactionalDirtyInstance();
- case DETACHED_CLEAN:
- return getDetachedCleanInstance();
- case DETACHED_DIRTY:
- return getDetachedDirtyInstance();
- default:
- return null;
- }
- }
-
- /** */
- public 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]);
- }
- return null;
- }
- return obj;
- }
-
- /** */
- public 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]);
- }
- return null;
- }
- return obj;
- }
-
- /** */
- public StateTransitionObj getPersistentCleanInstance()
- {
- StateTransitionObj obj = getHollowInstance();
- if( obj == null ) return null;
- StateTransitionObj sto = (StateTransitionObj) obj;
- 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]);
- }
- 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]);
- }
- 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
-
- prepareTransactionAndJDOSettings(transaction);
-
- 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]);
- }
- 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]);
- }
- 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]);
- }
- 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]);
- }
- 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]);
- }
- 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]);
- }
- return null;
- }
- return obj;
- }
-
- /** */
- public StateTransitionObj getPersistentNontransactionalDirtyInstance()
- {
- StateTransitionObj obj = getPersistentNontransactionalInstance();
- if( obj == null ) return null;
- obj.writeField(10000);
- int curr = currentState(obj);
- if( curr != PERSISTENT_NONTRANSACTIONAL_DIRTY ) {
- if (debug) {
- logger.debug("StateTransition: Unable to create persistent-nontransactional-dirty instance" +
- " from a persistent-clean instance via makeNontransactional()/JDOHelper.makeDirty," +
- " state is " + states[curr]);
- }
- return null;
- }
- return obj;
- }
-
- /** */
- public StateTransitionObj getDetachedCleanInstance()
- {
- StateTransitionObj obj = getHollowInstance();
- if( obj == null ) return null;
- obj = (StateTransitionObj) pm.detachCopy(obj);
- int curr = currentState(obj);
- if( curr != DETACHED_CLEAN ) {
- if (debug) {
- logger.debug("StateTransition: Unable to create detached-clean instance" +
- " from a persistent-clean instance via detachCopy," +
- " state is " + states[curr]);
- }
- return null;
- }
- return obj;
- }
-
- /** */
- public StateTransitionObj getDetachedDirtyInstance()
- {
- StateTransitionObj obj = getHollowInstance();
- if( obj == null ) return null;
- obj = (StateTransitionObj) pm.detachCopy(obj);
- obj.writeField(1000);
- int curr = currentState(obj);
- if( curr != DETACHED_DIRTY ) {
- if (debug) {
- logger.debug("StateTransition: Unable to create detached-dirty instance" +
- " from a persistent-clean instance via detachCopy/persistent field modification," +
- " state is " + states[curr]);
- }
- return null;
- }
- return obj;
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.Iterator;
+
+import javax.jdo.Extent;
+import javax.jdo.JDOFatalException;
+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 int DETACHALLONCOMMIT = 19;
+ private static final int DETACHCOPYOUTSIDETXNTRTRU = 20;
+ private static final int DETACHCOPYOUTSIDETXNTRFLS = 21;
+ private static final int DETACHCOPYINSIDEDATASTORETX = 22;
+ private static final int DETACHCOPYINSIDEOPTIMISTICTX = 23;
+ private static final int SERIALIZEOUTSIDETX = 24;
+ private static final int SERIALIZEDATASTORE = 25;
+ private static final int SERIALIZEOPTIMISTIC = 26;
+
+ private static final int NUM_OPERATIONS = 27;
+
+ 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",
+ "commit, detachAllOnCommit=true",
+ "detachCopy outside tx with NontransactionalRead=true",
+ "detachCopy outside tx with NontransactionalRead=false",
+ "detachCopy with active datastore tx",
+ "detachCopy with active optimistic tx",
+ "serialize outside tx",
+ "serialize with active datastore tx",
+ "serialize with active optimistic tx"
+ };
+
+ /**
+ * 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;
+ private static final int UNSPECIFIED = -5;
+
+ /**
+ * State transitions
+ */
+ public static final int[][] transitions = { // [operation] [current state] = new state
+ // TRANSIENT, PERSISTENT_NEW, PERSISTENT_CLEAN,
+ // PERSISTENT_DIRTY, HOLLOW, TRANSIENT_CLEAN,
+ // TRANSIENT_DIRTY, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
+ // PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL_DIRTY, DETACHED_CLEAN,
+ // DETACHED_DIRTY
+
+ // makePersistent
+ { PERSISTENT_NEW, UNCHANGED, UNCHANGED,
+ UNCHANGED, UNCHANGED, PERSISTENT_NEW,
+ PERSISTENT_NEW, UNCHANGED, UNCHANGED,
+ UNCHANGED, UNCHANGED, DETACHED_CLEAN,
+ DETACHED_DIRTY},
+
+ // deletePersistent
+ { ERROR, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
+ PERSISTENT_DELETED, PERSISTENT_DELETED, ERROR,
+ ERROR, UNCHANGED, UNCHANGED,
+ PERSISTENT_DELETED, PERSISTENT_DELETED, ERROR,
+ ERROR},
+
+ // makeTransactional
+ { TRANSIENT_CLEAN, UNCHANGED, UNCHANGED,
+ UNCHANGED, PERSISTENT_CLEAN, UNCHANGED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ PERSISTENT_CLEAN, PERSISTENT_DIRTY, ERROR,
+ ERROR},
+
+ // makeNontransactional
+ { ERROR, ERROR, PERSISTENT_NONTRANSACTIONAL,
+ ERROR, UNCHANGED, TRANSIENT,
+ ERROR, ERROR, ERROR,
+ UNCHANGED, UNCHANGED, ERROR,
+ ERROR},
+
+ // makeTransient
+ { UNCHANGED, ERROR, TRANSIENT,
+ ERROR, TRANSIENT, UNCHANGED,
+ UNCHANGED, ERROR, ERROR,
+ TRANSIENT, ERROR, ERROR,
+ ERROR},
+
+ // commit, retainValues = false
+ { UNCHANGED, HOLLOW, HOLLOW,
+ HOLLOW, UNCHANGED, UNCHANGED,
+ TRANSIENT_CLEAN, TRANSIENT, TRANSIENT,
+ UNCHANGED, HOLLOW, UNCHANGED,
+ UNCHANGED},
+
+ // commit, retainValues = true
+ { UNCHANGED, PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL,
+ PERSISTENT_NONTRANSACTIONAL, UNCHANGED, UNCHANGED,
+ TRANSIENT_CLEAN, TRANSIENT, TRANSIENT,
+ UNCHANGED, PERSISTENT_NONTRANSACTIONAL, UNCHANGED,
+ UNCHANGED},
+
+ // TRANSIENT, PERSISTENT_NEW, PERSISTENT_CLEAN,
+ // PERSISTENT_DIRTY, HOLLOW, TRANSIENT_CLEAN,
+ // TRANSIENT_DIRTY, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
+ // PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL_DIRTY, DETACHED_CLEAN,
+ // DETACHED_DIRTY
+
+ // rollback, restoreValues = false
+ { UNCHANGED, TRANSIENT, HOLLOW,
+ HOLLOW, UNCHANGED, UNCHANGED,
+ TRANSIENT_CLEAN, TRANSIENT, HOLLOW,
+ UNCHANGED, HOLLOW, UNCHANGED,
+ UNCHANGED},
+
+ // rollback, restoreValues = true
+ { UNCHANGED, TRANSIENT, PERSISTENT_NONTRANSACTIONAL,
+ PERSISTENT_NONTRANSACTIONAL, UNCHANGED, UNCHANGED,
+ TRANSIENT_CLEAN, TRANSIENT, PERSISTENT_NONTRANSACTIONAL,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED},
+
+ // refresh with active datastore transaction
+ { UNCHANGED, UNCHANGED, UNCHANGED,
+ PERSISTENT_CLEAN, UNCHANGED, UNCHANGED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, PERSISTENT_NONTRANSACTIONAL, UNCHANGED,
+ UNCHANGED},
+
+ // refresh with active optimistic transaction
+ { UNCHANGED, UNCHANGED, UNCHANGED,
+ PERSISTENT_NONTRANSACTIONAL, UNCHANGED, UNCHANGED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, PERSISTENT_NONTRANSACTIONAL, UNCHANGED,
+ UNCHANGED},
+
+ // evict
+ { NOT_APPLICABLE, UNCHANGED, HOLLOW,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ HOLLOW, HOLLOW, UNCHANGED,
+ UNCHANGED},
+
+ // read field outside transaction
+ { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE,
+ IMPOSSIBLE, PERSISTENT_NONTRANSACTIONAL, IMPOSSIBLE,
+ IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED},
+
+ // read field with active optimistic transaction
+ { UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, PERSISTENT_NONTRANSACTIONAL, UNCHANGED,
+ UNCHANGED, UNSPECIFIED, UNSPECIFIED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED},
+
+ // TRANSIENT, PERSISTENT_NEW, PERSISTENT_CLEAN,
+ // PERSISTENT_DIRTY, HOLLOW, TRANSIENT_CLEAN,
+ // TRANSIENT_DIRTY, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
+ // PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL_DIRTY, DETACHED_CLEAN,
+ // DETACHED_DIRTY
+
+ // read field with active datastore transaction
+ { UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, PERSISTENT_CLEAN, UNCHANGED,
+ UNCHANGED, UNSPECIFIED, UNSPECIFIED,
+ PERSISTENT_CLEAN, UNCHANGED, UNCHANGED,
+ UNCHANGED},
+
+ // write field outside transaction
+ { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE,
+ IMPOSSIBLE, PERSISTENT_NONTRANSACTIONAL, IMPOSSIBLE,
+ IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
+ UNCHANGED, UNCHANGED, DETACHED_DIRTY,
+ UNCHANGED},
+
+ // write field with active transaction
+ { UNCHANGED, UNCHANGED, PERSISTENT_DIRTY,
+ UNCHANGED, PERSISTENT_DIRTY, TRANSIENT_DIRTY,
+ UNCHANGED, ERROR, ERROR,
+ PERSISTENT_DIRTY, UNCHANGED, DETACHED_DIRTY,
+ UNCHANGED},
+
+ // retrieve outside transaction
+ { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE,
+ IMPOSSIBLE, PERSISTENT_NONTRANSACTIONAL, IMPOSSIBLE,
+ IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED},
+
+ // retrieve with active transaction
+ { UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, PERSISTENT_CLEAN, UNCHANGED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ PERSISTENT_CLEAN, UNCHANGED, UNCHANGED,
+ UNCHANGED},
+
+ // commit, detachAllOnCommit = true
+ { UNCHANGED, DETACHED_CLEAN, DETACHED_CLEAN,
+ DETACHED_CLEAN, DETACHED_CLEAN, UNCHANGED,
+ TRANSIENT_CLEAN, TRANSIENT, TRANSIENT,
+ DETACHED_CLEAN, DETACHED_CLEAN, UNCHANGED,
+ UNCHANGED},
+
+ // TRANSIENT, PERSISTENT_NEW, PERSISTENT_CLEAN,
+ // PERSISTENT_DIRTY, HOLLOW, TRANSIENT_CLEAN,
+ // TRANSIENT_DIRTY, PERSISTENT_NEW_DELETED, PERSISTENT_DELETED,
+ // PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NONTRANSACTIONAL_DIRTY, DETACHED_CLEAN,
+ // DETACHED_DIRTY
+
+ // detachCopy outside tx with NontransactionalRead=true
+ { ERROR, IMPOSSIBLE, IMPOSSIBLE,
+ IMPOSSIBLE, PERSISTENT_NONTRANSACTIONAL, ERROR,
+ IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
+ UNCHANGED, UNSPECIFIED, UNCHANGED,
+ UNSPECIFIED},
+
+ // detachCopy outside tx with NontransactionalRead=false
+ { ERROR, IMPOSSIBLE, IMPOSSIBLE,
+ IMPOSSIBLE, ERROR, ERROR,
+ IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
+ ERROR, ERROR, ERROR,
+ ERROR},
+
+ // detachCopy with active datastore tx
+ { PERSISTENT_NEW, UNCHANGED, UNCHANGED,
+ UNCHANGED, PERSISTENT_CLEAN, PERSISTENT_NEW,
+ PERSISTENT_NEW, ERROR, ERROR,
+ UNCHANGED, IMPOSSIBLE, UNCHANGED,
+ UNCHANGED},
+
+ // detachCopy with active optimistic tx
+ { PERSISTENT_NEW, UNCHANGED, UNCHANGED,
+ UNCHANGED, PERSISTENT_NONTRANSACTIONAL, PERSISTENT_NEW,
+ PERSISTENT_NEW, ERROR, ERROR,
+ UNCHANGED, IMPOSSIBLE, UNCHANGED,
+ UNCHANGED},
+
+ // serialize outside tx
+ { UNCHANGED, IMPOSSIBLE, IMPOSSIBLE,
+ IMPOSSIBLE, UNCHANGED, IMPOSSIBLE,
+ IMPOSSIBLE, IMPOSSIBLE, IMPOSSIBLE,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED},
+
+ // serialize with active datastore tx
+ { UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, PERSISTENT_CLEAN, UNCHANGED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ PERSISTENT_CLEAN, UNCHANGED, UNCHANGED,
+ UNCHANGED},
+
+ // serialize with active optimistic tx
+ { UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED, UNCHANGED, UNCHANGED,
+ UNCHANGED},
+ };
+
+ 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
+ { true, true, false }, // commit, DetachAllOnCommit = true
+ { false, false, true }, // detachCopy outside tx with NonTransactionaRead=true
+ { false, false, true }, // detachCopy outside tx with NonTransactionaRead=false
+ { true, false, false }, // detachCopy with active datastore tx
+ { false, true, false }, // detachCopy with active optimistic tx
+ { false, false, true }, // serialize outside tx
+ { true, false, false }, // serialize with active datastore tx
+ { false, true, false } // serialize with active optimistic tx
+ };
+
+ /**
+ * @see JDO_Test#localSetUp()
+ */
+ protected void localSetUp() {
+ pm = getPM();
+ addTearDownClass(StateTransitionObj.class);
+ generatePersistentInstances();
+ }
+
+ public void test() {
+ scenario = DATASTORE_TX;
+ checkTransitions();
+
+ if( isOptimisticSupported() ){
+ scenario = OPTIMISTIC_TX;
+ checkTransitions();
+ }
+
+ scenario = NO_TX;
+ checkTransitions();
+ failOnError();
+ }
+
+ /** */
+ 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;
+ }
+
+ /** */
+ public void prepareTransactionAndJDOSettings(Transaction transaction) {
+ if( scenario != NO_TX ) {
+ transaction.setNontransactionalRead(false);
+ transaction.setNontransactionalWrite(false);
+
+ if( operation == COMMITNORETAINVALUES )
+ transaction.setRetainValues(false);
+ if( operation == COMMITRETAINVALUES )
+ transaction.setRetainValues(true);
+ if( operation == ROLLBACKNORESTOREVALUES )
+ transaction.setRestoreValues(false);
+ if( operation == ROLLBACKRESTOREVALUES )
+ transaction.setRestoreValues(true);
+ if( operation == DETACHALLONCOMMIT )
+ pm.setDetachAllOnCommit(true);
+ else
+ pm.setDetachAllOnCommit(false);
+
+ transaction.setOptimistic(scenario == OPTIMISTIC_TX);
+ transaction.begin();
+ if( !transaction.isActive() )
+ if (debug)
+ logger.debug("StateTransitions: Transaction should be active, but it is not");
+ } else {
+ if( operation == READOUTSIDETX ||
+ operation == RETRIEVEOUTSIDETX ||
+ operation == DETACHCOPYOUTSIDETXNTRTRU ||
+ operation == SERIALIZEOUTSIDETX ) {
+ transaction.setNontransactionalRead(true);
+ }
+ if( operation == WRITEOUTSIDETX ||
+ current_state == PERSISTENT_NONTRANSACTIONAL_DIRTY) {
+ transaction.setNontransactionalWrite(true);
+ }
+ }
+ }
+
+ /** */
+ 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 ||
+ operation == RETRIEVEOUTSIDETX ||
+ operation == DETACHCOPYOUTSIDETXNTRTRU ||
+ operation == SERIALIZEOUTSIDETX) &&
+ !isNontransactionalReadSupported() ) continue;
+ if( operation == WRITEOUTSIDETX && !isNontransactionalWriteSupported() ) continue;
+ if( operation == COMMITRETAINVALUES && !isRetainValuesSupported() ) continue;
+ if( operation == MAKENONTRANSACTIONAL &&
+ !(isNontransactionalReadSupported() || isNontransactionalWriteSupported()) )
+ continue;
+ int NUM_JDO1_STATES = NUM_STATES - 2; // JDO1 is tested so far here.
+ for( current_state = 0; current_state < NUM_JDO1_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
+ if( current_state == PERSISTENT_NONTRANSACTIONAL_DIRTY &&
+ !isNontransactionalWriteSupported() )
+ continue;
+
+ expected_state = transitions[operation][current_state];
+ if( expected_state == IMPOSSIBLE ) continue;
+ if( expected_state == NOT_APPLICABLE ) continue;
+ if( expected_state == UNSPECIFIED ) 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();
+ }
+
+ prepareTransactionAndJDOSettings(transaction);
+
+ printSituation();
+
+ 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 {
+ appendMessage(ASSERTION_FAILED + NL +
+ "StateTransitions: " +
+ scenario_string[scenario] +
+ "; current state " + states[current_state] + NL +
+ operations[operation] +
+ "; unexpected exception:" + excep);
+ continue;
+ }
+ }
+
+ // Get new state, verify correct transition and exceptions occurred
+ new_state = currentState(obj);
+ if( expected_state == ERROR ){
+ if( e == null ){
+ appendMessage(ASSERTION_FAILED + NL +
+ "StateTransitions: " +
+ scenario_string[scenario] +
+ "; current state " + states[current_state] + NL +
+ operations[operation] +
+ "; JDOUserException should have been thrown");
+ } else {
+ if( new_state != current_state ){
+ appendMessage(ASSERTION_FAILED + NL +
+ "StateTransitions: " +
+ scenario_string[scenario] +
+ "; current state " + states[current_state] + NL +
+ operations[operation] +
+ "; JDOUserException properly thrown, but instance should remain in current state," +
+ "instance changed state to " + states[new_state]);
+ }
+ }
+ }
+ if( !compareStates(new_state, expected_state) ) {
+ appendMessage(ASSERTION_FAILED + NL +
+ "StateTransitions: " +
+ scenario_string[scenario] +
+ "; current state " + states[current_state] + NL +
+ operations[operation] +
+ " transitioned instance to invalid state " + states[new_state] +
+ "; expected state " + states[expected_state]);
+ }
+ if( transaction.isActive() ) transaction.rollback();
+ }
+ catch(Exception unexpected_exception) {
+ if (transaction.isActive())
+ transaction.rollback();
+ appendMessage(ASSERTION_FAILED + NL +
+ "StateTransitions: " +
+ scenario_string[scenario] +
+ "; current state " + states[current_state] + NL +
+ operations[operation] +
+ "; unexpected exception caught: " + 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:
+ {
+ obj.readField();
+ break;
+ }
+ case READOPTIMISTIC:
+ {
+ obj.readField();
+ break;
+ }
+ case READDATASTORE:
+ {
+ 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;
+ }
+ case DETACHALLONCOMMIT:
+ {
+ pm.currentTransaction().commit();
+ break;
+ }
+ case DETACHCOPYOUTSIDETXNTRTRU:
+ {
+ pm.detachCopy(obj);
+ break;
+ }
+ case DETACHCOPYOUTSIDETXNTRFLS:
+ {
+ pm.detachCopy(obj);
+ break;
+ }
+ case DETACHCOPYINSIDEDATASTORETX:
+ {
+ pm.detachCopy(obj);
+ break;
+ }
+ case DETACHCOPYINSIDEOPTIMISTICTX:
+ {
+ pm.detachCopy(obj);
+ break;
+ }
+ case SERIALIZEOUTSIDETX:
+ {
+ ObjectOutputStream oos = null;
+ try {
+ oos = new ObjectOutputStream(new ByteArrayOutputStream());
+ oos.writeObject(obj);
+ } catch (IOException e) {
+ throw new JDOFatalException(e.getMessage(), e);
+ } finally {
+ if (oos != null) {
+ try {
+ oos.close();
+ } catch (IOException e) {
+ throw new JDOFatalException(e.getMessage(), e);
+ }
+ }
+ }
+ break;
+ }
+ case SERIALIZEDATASTORE:
+ case SERIALIZEOPTIMISTIC:
+ {
+ ObjectOutputStream oos = null;
+ try {
+ oos = new ObjectOutputStream(new ByteArrayOutputStream());
+ oos.writeObject(obj);
+ } catch (IOException e) {
+ throw new JDOFatalException(e.getMessage(), e);
+ } finally {
+ if (oos != null) {
+ try {
+ oos.close();
+ } catch (IOException e) {
+ throw new JDOFatalException(e.getMessage(), e);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ {
+ appendMessage(ASSERTION_FAILED + NL +
+ "StateTransitions: " +
+ scenario_string[scenario] +
+ "; internal error, illegal operation: " + operation);
+ }
+ }
+ }
+
+ /**
+ * Get an instance in the specified state.
+ */
+ public 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();
+ case PERSISTENT_NONTRANSACTIONAL_DIRTY:
+ return getPersistentNontransactionalDirtyInstance();
+ case DETACHED_CLEAN:
+ return getDetachedCleanInstance();
+ case DETACHED_DIRTY:
+ return getDetachedDirtyInstance();
+ default:
+ return null;
+ }
+ }
+
+ /** */
+ public 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]);
+ }
+ return null;
+ }
+ return obj;
+ }
+
+ /** */
+ public 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]);
+ }
+ return null;
+ }
+ return obj;
+ }
+
+ /** */
+ public StateTransitionObj getPersistentCleanInstance()
+ {
+ StateTransitionObj obj = getHollowInstance();
+ if( obj == null ) return null;
+ StateTransitionObj sto = (StateTransitionObj) obj;
+ 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]);
+ }
+ 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]);
+ }
+ return null;
+ }
+ return obj;
+ }
+
+ /** */
+ public StateTransitionObj getHollowInstance()
+ {
+ Extent extent = pm.getExtent(StateTransitionObj.class, false);
+ Iterator iter = extent.iterator();
+ if( !iter.hasNext() ){
+ if (debug)
[... 174 lines stripped ...]