db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fuzzylo...@apache.org
Subject svn commit: r155990 [13/15] - in incubator/derby/code/trunk: ./ java/testing/ java/testing/org/apache/derbyTesting/functionTests/harness/ java/testing/org/apache/derbyTesting/functionTests/master/ java/testing/org/apache/derbyTesting/functionTests/suites/ java/testing/org/apache/derbyTesting/functionTests/tests/lang/ java/testing/org/apache/derbyTesting/functionTests/tests/store/ java/testing/org/apache/derbyTesting/functionTests/tests/unit/ java/testing/org/apache/derbyTesting/unitTests/ java/testing/org/apache/derbyTesting/unitTests/crypto/ java/testing/org/apache/derbyTesting/unitTests/harness/ java/testing/org/apache/derbyTesting/unitTests/lang/ java/testing/org/apache/derbyTesting/unitTests/services/ java/testing/org/apache/derbyTesting/unitTests/store/ java/testing/org/apache/derbyTesting/unitTests/util/
Date Thu, 03 Mar 2005 01:30:47 GMT
Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Util.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Util.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Util.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Util.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,1448 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_Util
+
+   Copyright 1997, 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   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.derbyTesting.unitTests.store;
+
+import org.apache.derby.iapi.store.raw.*;
+
+import org.apache.derby.iapi.services.io.FormatableBitSet;
+
+import org.apache.derby.iapi.reference.Property;
+
+// impl imports are the preferred way to create unit tests.
+import org.apache.derbyTesting.unitTests.harness.T_MultiThreadedIterations;
+import org.apache.derbyTesting.unitTests.harness.T_Fail;
+
+import org.apache.derby.iapi.services.context.ContextService;
+import org.apache.derby.iapi.services.context.ContextManager;
+import org.apache.derby.iapi.services.locks.*;
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.store.access.AccessFactoryGlobals;
+import org.apache.derby.iapi.store.access.Qualifier;
+
+import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+
+
+import org.apache.derby.iapi.reference.Attribute;
+import org.apache.derby.iapi.services.property.PropertyUtil;
+import org.apache.derby.iapi.error.ExceptionSeverity;
+import java.io.*;
+import java.util.Properties;
+import org.apache.derby.iapi.types.SQLChar;
+
+
+/*
+  Utility class to help test raw store functionality.  
+
+  If you write a raw store unit test, be that a protocol test or an
+  implementation test, and find youself needing to do certain operations over
+  and over again, chances are that functionality is either in here or should be
+  added.  This class is here entirely for the convenience of people writing
+  unit tests for the RawStore.
+*/
+public class T_Util
+{ 
+
+	RawStoreFactory	rsFactory;
+	LockFactory  lFactory;
+	ContextService csFactory;
+
+	private int		openContainerMode;	// mode flags used in openContainer
+
+	public T_Util(RawStoreFactory rsf, LockFactory lf, 
+				  ContextService csf)
+	{
+		rsFactory = rsf;
+		lFactory = lf;
+		csFactory = csf;
+
+		openContainerMode = 0; // logged by default
+	}
+
+	public void setOpenMode(int newMode) {
+		openContainerMode = newMode;
+	}
+
+	/*
+	 * function that checks for a condition, throws T_Fail exception if the condition
+	 * is not met.
+	 */
+
+	/*
+	 * check that transaction does not hold any lock
+	 */
+	public void t_checkNullLockCount(Transaction t) throws T_Fail {
+		if (lFactory.areLocksHeld(t))
+			throw T_Fail.testFailMsg("Previous action did not clean up all locks.");
+	}
+
+	/*
+	 * check that page number on the page matches the input page number
+	 */
+	public static void t_checkPageNumber(Page page, long pageNumber) throws T_Fail {
+		if (page.getPageNumber() != pageNumber)
+			throw T_Fail.testFailMsg("page number expected to be " + pageNumber + ", is " +
+				page.getPageNumber());
+	}
+
+	/*
+	 * check that the number of record on the page matches input.  
+	 * @param page the page in question
+	 * @param count the total number of record - this include deleted as well as non-deleted
+	 * @param nonDeleted the number of non-deleted record
+	 */
+	public static void t_checkRecordCount(Page page, int count, int nonDeleted) throws T_Fail, StandardException {
+		if (page.recordCount() != count)
+			throw T_Fail.testFailMsg("recordCount() expected to be " + count + ", is " + page.recordCount());
+
+		if (page.nonDeletedRecordCount() != nonDeleted)
+			throw T_Fail.testFailMsg("nonDeletedRecordCount() expected to be " + nonDeleted + ", is " + page.nonDeletedRecordCount());
+	}
+
+	/*
+	 * check the number of fields in the slot
+	 */
+	public static void t_checkFieldCount(Page page, int slot, int count) throws T_Fail, StandardException {
+		if (page.fetchNumFieldsAtSlot(slot) != count)
+			throw T_Fail.testFailMsg("number of fields at slot " + slot + " expected to be " + count
+									 + ", is " + page.fetchNumFieldsAtSlot(slot));
+	}
+
+	/**
+		Fetch a record that is expected to exist using a record handle.
+		The record has a T_RawStoreRow of 1 column and this column as value as
+		specified by data, which could be null.
+
+		Calls recordExists() before fetch to ensure that the record
+		is there.
+
+		@param page the page in question
+		@param rh the record handle
+		@param data the string value that is expected in the row
+
+		@exception T_Fail Implementation failed expectation
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#recordExists
+		@see Page#fetch
+	*/
+	public static void t_checkFetch(Page page, RecordHandle rh, String data, int stringLen)
+		throws T_Fail, StandardException {
+
+		t_checkFetch(page, rh, T_Util.getStringFromData(data, stringLen));
+	}
+	
+	public static void t_checkFetch(Page page, RecordHandle rh, String data)
+		throws T_Fail, StandardException {
+
+		if (!page.recordExists(rh, false))
+			throw T_Fail.testFailMsg("Record does not exist");
+
+		T_RawStoreRow readRow = new T_RawStoreRow((String) null);
+
+		int slot = page.getSlotNumber(rh);
+
+		RecordHandle rhf = 
+            page.fetchFromSlot(
+                rh, slot, readRow.getRow(), 
+                (FetchDescriptor) null,
+                false);
+
+		if (rhf == null)
+			throw T_Fail.testFailMsg("Failed to read record");
+
+		if ((data == null) || readRow.getStorableColumn(0).isNull()) {
+
+			if ((data == null) && readRow.getStorableColumn(0).isNull())
+				return;
+
+			throw T_Fail.testFailMsg("Record's value incorrect");
+		}
+
+		if (!readRow.toString().equals(data))
+			throw T_Fail.testFailMsg("Record's value incorrect, expected :" + data + ": - got :" + readRow.toString());
+	}
+
+	/**
+		Fetch a record from a container that is expected to exist using a record handle.
+		Calls recordExists() before fetch to ensure that the record
+		is there.
+
+		@exception T_Fail Implementation failed expectation
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#recordExists
+		@see Page#fetch
+	*/
+	public void t_checkFetch(ContainerHandle c, RecordHandle rh, String data)
+		throws T_Fail, StandardException {
+
+		Page page = t_getPage(c, rh.getPageNumber());
+
+		try
+		{
+			t_checkFetch(page, rh, data);
+		}
+		finally
+		{
+			page.unlatch();
+		}
+	}
+
+	/**
+		Check to make sure record is NOT there
+
+		@exception T_Fail Implementation failed expectation
+		@exception StandardException Unexpected exception from the implementation
+	 */
+	public void t_checkFetchFail(ContainerHandle c, RecordHandle rh)
+		throws T_Fail, StandardException 
+	{
+		Page page = t_getPage(c, rh.getPageNumber());
+
+		try
+		{
+			if (page.recordExists(rh, true))
+				throw T_Fail.testFailMsg("Record Exists");
+		}
+		finally
+		{
+			page.unlatch();
+		}
+	}
+
+	/**
+		Fetch a deleted record from a container using a record handle.
+
+		@exception T_Fail Implementation failed expectation
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#recordExists
+		@see Page#fetch
+	*/
+	public void t_checkFetchDeleted(ContainerHandle c, RecordHandle rh, 
+									String data)
+		throws T_Fail, StandardException 
+	{
+		Page p = t_getPage(c, rh.getPageNumber());
+		if (p == null)
+			throw T_Fail.testFailMsg("Page not found " + rh);
+
+		T_RawStoreRow readRow = new T_RawStoreRow((String) null);
+
+		try
+		{
+			int slot = p.getSlotNumber(rh);
+			if (p.fetchFromSlot(
+                    rh, slot, readRow.getRow(), 
+                    (FetchDescriptor) null,
+                    false) != null)
+            {
+				throw T_Fail.testFailMsg(
+                    "Record at slot " + slot + " not deleted");
+            }
+		}
+		finally
+		{
+			p.unlatch();
+		}
+	}
+
+
+	/*
+		Fetch a record that is expected to exist using a record handle.
+		The record contains the values in the passed in row, which is a
+		T_RawStoreRow.  A T_RawStoreRow of the same number of columns will be made and fetched
+		from the page and compared with the passed in row.
+
+	*/
+	public static void t_checkFetch(Page page, RecordHandle rh, T_RawStoreRow row)
+		throws T_Fail, StandardException 
+	{
+		if (!page.recordExists(rh, false))
+			throw T_Fail.testFailMsg("Record does not exist");
+
+		// try to fetch the same number of columns as the passed in row
+		int ncol = row.nColumns();
+		T_RawStoreRow readRow = new T_RawStoreRow(ncol);
+		for (int i = 0; i < ncol; i++)
+			readRow.setColumn(i, (String) null);
+
+		RecordHandle rhf = page.fetch(rh, readRow.getRow(), (FormatableBitSet) null, false);
+		if (rhf == null)
+			throw T_Fail.testFailMsg("Failed to read record");
+		if (!readRow.toString().equals(row.toString()))
+			throw T_Fail.testFailMsg("Record's value incorrect, expected :" +
+									 row.toString() + ": - got :" + readRow.toString());
+	}
+
+
+	/*
+	    Using sparse row representation:
+		Fetch a column of a record that is expected to exist, using a record 
+		handle and a FormatableBitSet object.
+		Check that column colNum has value data.
+	*/
+	public static void t_checkFetchCol(Page page, RecordHandle rh, int colNum,
+									   int numCols, String data)
+		throws T_Fail, StandardException 
+	{
+		if (!page.recordExists(rh, false))
+			throw T_Fail.testFailMsg("Record does not exist");
+
+		T_RawStoreRow readRow = new T_RawStoreRow(numCols);
+		for (int i = 0; i < numCols; i++)
+			readRow.setColumn(i, (String) null);
+		FormatableBitSet colList = new FormatableBitSet(numCols);
+		colList.set(colNum);
+
+		RecordHandle rhf = page.fetch(rh, readRow.getRow(), colList, false);
+		if (rhf == null)
+			throw T_Fail.testFailMsg("Failed to read record");
+		String col = readRow.getStorableColumn(colNum).toString();
+		if (!col.equals(data))
+			throw T_Fail.testFailMsg("Record's value for column " + colNum +
+									 " incorrect, expected :" + data +
+									 ": - got :" + readRow.toString());
+	}
+
+
+	/*
+	 * the following is a sequence of fetches, fetching the first row, fetching
+	 * the next and previous rows, and fetching the last row in the page.
+	 *
+	 * The row is assumed to be a T_RawStoreRow with 1 column, which value is the
+	 * string specified in data.
+	 */
+
+	/*
+	 * fetch and check the first row in the page.  
+	 * Return the first row's recordHandle. 
+	 */
+	public static RecordHandle t_checkFetchFirst(Page page, String data)
+		throws T_Fail, StandardException {
+		T_RawStoreRow readRow = new T_RawStoreRow((String) null);
+
+        int slot = 0;
+        while (page.isDeletedAtSlot(slot))
+        {
+            slot++;
+        }
+
+		RecordHandle rhf = 
+            page.fetchFromSlot(
+                (RecordHandle) null, slot, 
+                readRow.getRow(), 
+                (FetchDescriptor) null,
+                false);
+
+		if (rhf == null)
+			throw T_Fail.testFailMsg("Failed to read record");
+		if (!readRow.toString().equals(data))
+			throw T_Fail.testFailMsg("Record's value incorrect, expected :" + data + ": - got :" + readRow.toString());
+
+		return rhf;
+	}
+
+	/*
+	 * Fetch and check the next (next to rh) row in the page.
+	 * Return the next row's recordHandle
+	 */
+	public static RecordHandle t_checkFetchNext(Page page, RecordHandle rh, String data)
+		throws T_Fail, StandardException {
+
+		if (!page.recordExists(rh, false))
+			throw T_Fail.testFailMsg("Record does not exist");
+
+		T_RawStoreRow readRow = new T_RawStoreRow((String) null);
+
+        int slot = page.getSlotNumber(rh) + 1;
+        while (page.isDeletedAtSlot(slot))
+        {
+            slot++;
+        }
+
+		RecordHandle rhf = 
+            page.fetchFromSlot(
+                (RecordHandle) null, 
+                slot,
+                readRow.getRow(), 
+                (FetchDescriptor) null,
+                false);
+
+		if (rhf == null)
+			throw T_Fail.testFailMsg("Failed to read record");
+		if (!readRow.toString().equals(data))
+			throw T_Fail.testFailMsg("Record's value incorrect, expected :" + data + ": - got :" + readRow.toString());
+
+		return rhf;
+	}
+	
+	/*
+	 * Fetch and check the previous (previous to rh) row in the page.
+	 * Return the previous row's recordHandle
+	 */
+	public static RecordHandle t_checkFetchPrevious(Page page, RecordHandle rh, String data)
+		throws T_Fail, StandardException {
+
+		if (!page.recordExists(rh, false))
+			throw T_Fail.testFailMsg("Record does not exist");
+
+		T_RawStoreRow readRow = new T_RawStoreRow((String) null);
+
+        int slot = page.getSlotNumber(rh) - 1;
+
+        while (page.isDeletedAtSlot(slot) && slot >= 0)
+        {
+            slot--;
+        }
+
+        if (slot == -1)
+            return(null);
+
+
+		RecordHandle rhf = 
+            page.fetchFromSlot(
+                (RecordHandle) null, 
+                slot,
+                readRow.getRow(), 
+                (FetchDescriptor) null,
+                false);
+
+		if (rhf == null)
+			throw T_Fail.testFailMsg("Failed to read record");
+		if (!readRow.toString().equals(data))
+			throw T_Fail.testFailMsg("Record's value incorrect, expected :" + data + ": - got :" + readRow.toString());
+
+		return rhf;
+	}
+
+	/*
+	 * Fetch and check the last row in the page.
+	 * Return the last row's recordHandle
+	 */
+	public static RecordHandle t_checkFetchLast(Page page, String data)
+		throws T_Fail, StandardException {
+		T_RawStoreRow readRow = new T_RawStoreRow((String) null);
+
+        int slot = page.recordCount() - 1;
+        while (page.isDeletedAtSlot(slot) && slot >= 0)
+        {
+            slot--;
+        }
+
+        if (slot == -1)
+            return(null);
+
+		RecordHandle rhf = 
+            page.fetchFromSlot(
+                (RecordHandle) null, 
+                slot,
+                readRow.getRow(),
+                (FetchDescriptor) null,
+                false);
+
+		if (rhf == null)
+			throw T_Fail.testFailMsg("Failed to read record");
+		if (!readRow.toString().equals(data))
+			throw T_Fail.testFailMsg("Record's value incorrect, expected :" + data + ": - got :" + readRow.toString());
+
+		return rhf;
+	}
+
+
+	/*
+	 * Fetch and check the slot on the page.  
+	 *
+	 * The slot number is NOT a stable reference once the page is unlatched,
+	 * this check is only valid if you know the page has not been unlatched
+	 * since you put the row in, or you know nobody has touched the page since
+	 * you determined the slot number
+	 *
+	 * The slot refers to a row in the page which has a T_RawStoreRow of 1 column, the
+	 * column has the value of data input.
+	 *
+	 * @param page the page in question
+	 * @param slot the slot number (see above)
+	 * @param data the column value
+	 * @param deleted if the row is deleted, set to true
+	 * @param forUpdate If you want to lock the row for update, set forUpdate to true.
+	 *
+	 */
+	public static void t_checkFetchBySlot(Page page, int slot, 
+									String data, boolean deleted, 
+									boolean forUpdate)
+		throws T_Fail, StandardException 
+	{
+		T_RawStoreRow readRow = new T_RawStoreRow((String) null);
+		RecordHandle rh = 
+            page.fetchFromSlot(
+                (RecordHandle) null, slot, 
+                readRow.getRow(),
+                (FetchDescriptor) null,
+                true);
+
+		if (rh == null)
+			throw T_Fail.testFailMsg("Failed to read record");
+		if (!readRow.toString().equals(data))
+			throw T_Fail.testFailMsg("Record's value incorrect, expected :" + data + ": - got :" + readRow.toString());
+
+		if (page.isDeletedAtSlot(slot) != deleted)
+			throw T_Fail.testFailMsg("Record at slot " + slot + " deleted=" +
+									 page.isDeletedAtSlot(slot) + ", expect " + deleted);
+
+		// RESOLVE: check locking
+	}
+
+	/*
+	 * check a column value from a slot on the page
+	 *
+	 * The slot number is NOT a stable reference once the page is unlatched,
+	 * this check is only valid if you know the page has not been unlatched
+	 * since you put the row in, or you know nobody has touched the page since
+	 * you determined the slot number
+	 *
+	 * The storable in the specified column put into the input column and it
+	 * is check for the same value as the input data 
+	 *
+	 * @param page the page in question
+	 * @param slot the slot number (see above)
+	 * @param fieldId the field Id on the row
+	 * @param column the storable to put the column in
+	 * @param forUpdate true if you want to lock the row for update
+	 * @param data the expected value in the column
+	 */
+	public static void t_checkFetchColFromSlot(Page page,
+										 int slot,
+										 int fieldId,
+										 DataValueDescriptor column,
+										 boolean forUpdate,
+										 String data,
+										 int stringLen)
+		 throws StandardException, T_Fail
+	{
+		t_checkFetchColFromSlot(page, slot, fieldId, column, forUpdate, T_Util.getStringFromData(data, stringLen));
+	}
+	
+	public static void t_checkFetchColFromSlot(
+    Page                page,
+    int                 slot,
+    int                 fieldId,
+    DataValueDescriptor column,
+    boolean             forUpdate,
+    String              data)
+		 throws StandardException, T_Fail
+	{
+        DataValueDescriptor[] fetch_row = new DataValueDescriptor[fieldId + 1];
+        fetch_row[fieldId] = column;
+        FormatableBitSet validCols = new FormatableBitSet(fieldId + 1);
+        validCols.set(fieldId);
+
+		RecordHandle rh =
+			page.fetchFromSlot(
+                null, slot, fetch_row,
+                new FetchDescriptor(
+                    fetch_row.length, validCols, (Qualifier[][]) null), 
+                true);
+
+		if (rh == null)
+			throw T_Fail.testFailMsg("Failed to fetch record: slot "
+							 + slot + " field " + fieldId);
+
+		// RESOLVE - how to check rh lock mode?
+
+		if (data == null)
+		{
+			if (!column.isNull())
+				throw T_Fail.testFailMsg("Failed to fetch null column: slot "
+								 + slot + " field " + fieldId + " column is " + column);
+		}
+		else
+		{
+			if (column.isNull())
+				throw T_Fail.testFailMsg("expect non null column, got null: slot "
+								 + slot + " field " + fieldId);
+			if (!column.toString().equals(data))
+				throw T_Fail.testFailMsg("expect " + data + " got " + column.toString()
+								 + ": slot " + slot + " field " + fieldId);
+		}
+	}
+
+
+	/**
+		Take an empty page and check it does actually seem to be empty.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public static void t_checkEmptyPage(Page page) throws T_Fail, StandardException {
+
+		// check the counts
+		t_checkRecordCount(page, 0, 0);
+
+        try
+        {
+            page.fetchFromSlot(
+                (RecordHandle) null, 0, null, 
+                (FetchDescriptor) null,
+                false);
+
+            throw T_Fail.testFailMsg(
+                "fetchFromSlot() must throw exception on fetch from slot 0 on an empty page");
+        }
+        catch (StandardException se)
+        {
+            // expected exception.
+        }
+
+		// check we can't get a record handle. NB here we are guessing that 0
+		// and RecordHandle.FIRST_RECORD_ID might be valid record identifiers,
+		// nothing in the API states that they will be.  Eother way we
+		// shouldn't get a valid RecordHandle back.
+		if (page.getRecordHandle(0) != null)
+			throw T_Fail.testFailMsg("obtained a RecordHandle for an empty page");
+
+		if (page.getRecordHandle(RecordHandle.FIRST_RECORD_ID) != null)
+			throw T_Fail.testFailMsg("obtained a RecordHandle for an empty page");
+		
+		// should be no aux object
+		if (page.getAuxObject() != null)
+			throw T_Fail.testFailMsg("empty page has an aux object");
+
+		t_readOnlySlotOutOfRange(page, Page.FIRST_SLOT_NUMBER);
+
+		if (!page.spaceForInsert())
+			throw T_Fail.testFailMsg("spaceForInsert() returned false on an empty page");
+	}
+
+	/*
+		Check to see the correct behaviour for read only operations
+		that take a slot when the slot is out of range.
+	*/
+	public static void t_readOnlySlotOutOfRange(Page page, int slot) throws T_Fail, StandardException {
+
+		try {
+			page.fetchFromSlot(
+                (RecordHandle) null, slot, 
+                new DataValueDescriptor[0], 
+                (FetchDescriptor) null,
+                true);
+
+			throw T_Fail.testFailMsg("fetchFromSlot succeeded on out of range slot " + slot);
+		} catch (StandardException se0) {
+			// Statement exception expected, throw if not a statement exception.
+            if (se0.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                throw se0;
+		}
+		try {
+			page.isDeletedAtSlot(slot);
+			throw T_Fail.testFailMsg("isDeletedAtSlot succeeded on out of range slot " + slot);
+		} catch (StandardException se2) {
+			// Statement exception expected, throw if not a statement exception.
+            if (se2.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                throw se2;
+		}
+	}
+
+	/*
+		Check to see the correct behaviour for update operations
+		that take a slot when the slot is out of range.
+	*/
+	public static void t_updateSlotOutOfRange(Page page, int slot) throws T_Fail, StandardException {
+
+		try {
+			page.deleteAtSlot(slot, false, (LogicalUndo)null);
+			throw T_Fail.testFailMsg("deleteAtSlot succeeded on out of range slot " + slot);
+		} catch (StandardException se0) {
+			// Statement exception expected, throw if not a statement exception.
+            if (se0.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                throw se0;
+		}
+		try {
+			page.deleteAtSlot(slot, true, (LogicalUndo)null);
+			throw T_Fail.testFailMsg("deleteAtSlot succeeded on out of range slot " + slot);
+		} catch (StandardException se0) {
+			// Statement exception expected, throw if not a statement exception.
+            if (se0.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                throw se0;
+		}
+
+		T_RawStoreRow row = new T_RawStoreRow((String) null);
+
+		// insert at the last slot will succeed, so don't do it.
+		if (page.recordCount() != slot) {
+			try {			
+					page.insertAtSlot(slot, row.getRow(), (FormatableBitSet) null, (LogicalUndo)null,
+						Page.INSERT_DEFAULT, 100);
+					throw T_Fail.testFailMsg("insertAtSlot succeeded, on out of range slot " + slot);
+            } catch (StandardException se0) {
+                // Statement exception expected, throw if not a statement exception.
+                if (se0.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                    throw se0;
+            }
+		}
+
+		try {			
+			page.updateAtSlot(slot, row.getRow(), (FormatableBitSet) null);
+			throw T_Fail.testFailMsg("updateAtSlot succeeded on out of range slot " + slot);
+        } catch (StandardException se0) {
+            // Statement exception expected, throw if not a statement exception.
+            if (se0.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                throw se0;
+        }
+	}
+
+
+	/*
+	 * Save point checks
+	 */
+
+	/**
+		Negative test - check that an invalid savepoint is detected.
+	    
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public static void t_checkInvalidSavePoint(Transaction t, String name)
+		throws T_Fail, StandardException {
+
+		// check a non-existent save point is trapped
+		try {
+			t.rollbackToSavePoint(name, null);
+
+			throw T_Fail.testFailMsg("non existent save point did not cause exception on rollbackToSavePoint");
+		} catch (StandardException se) {
+			// we expected this ...
+		}
+		try {
+			t.releaseSavePoint(name, null);
+			throw T_Fail.testFailMsg("non existent save point did not cause exception on releaseSavePoint");
+
+		} catch (StandardException se) {
+			// we expected this ...
+		}
+	}
+
+	/* 
+	 * same as above, check an invalid savepoint in the given transaction
+	 * context
+	 */
+	public void t_checkInvalidSavePoint(T_TWC ctx, String name)
+		throws T_Fail, StandardException {
+		csFactory.setCurrentContextManager(ctx.cm);
+		try {
+		t_checkInvalidSavePoint(ctx.tran, name);
+		} finally {
+			csFactory.resetCurrentContextManager(ctx.cm);
+		}
+	}
+
+
+	/*
+	 * function that actually do something, start, commit, abort a trasaction,
+	 * get a page, insert a row, etc.
+	 */
+
+
+	/*
+		Start a user transaction, ensures that the startTransaction method
+		does not return null (which it shouldn't).
+	*/
+	public Transaction t_startTransaction() 
+		throws StandardException, T_Fail {
+			
+			Transaction t1 = 
+                rsFactory.startTransaction(
+                    csFactory.getCurrentContextManager(),
+					AccessFactoryGlobals.USER_TRANS_NAME);
+
+			if (t1 == null)
+				throw T_Fail.testFailMsg("Start a transaction");
+			t_checkNullLockCount(t1);
+			return t1;
+	}
+
+	/*
+		Start a user transaction, ensures that the startTransaction method
+		does not return null (which it shouldn't).
+	*/
+	public Transaction t_startGlobalTransaction(
+    int     format_id,
+    byte[]  global_id,
+    byte[]  branch_id) 
+		throws StandardException, T_Fail {
+
+			Transaction t1 = 
+                rsFactory.startGlobalTransaction(
+                    csFactory.getCurrentContextManager(),
+                    format_id, global_id, branch_id);
+
+			if (t1 == null)
+				throw T_Fail.testFailMsg("Start a transaction");
+			t_checkNullLockCount(t1);
+			return t1;
+	}
+
+	/*
+	 * start a user transaction with its own context (T_TWC)
+	 */
+	public T_TWC t_startTransactionWithContext()
+		throws StandardException, T_Fail
+	{
+		T_TWC ctx = new T_TWC(csFactory, lFactory, rsFactory);
+		ctx.startUserTransaction();
+		return ctx;
+	}
+
+	/*
+	 * start an internal transaction
+	 */
+	public Transaction t_startInternalTransaction() 
+		throws StandardException, T_Fail {
+
+			Transaction t1 = rsFactory.startInternalTransaction(csFactory.getCurrentContextManager());
+
+			if (t1 == null)
+				throw T_Fail.testFailMsg("Failed to start an internal transaction");
+			t_checkNullLockCount(t1);
+			return t1;
+	}
+
+	/*
+	 * commit a transaction
+	 */
+	public void t_commit(Transaction t) 
+		throws StandardException, T_Fail {
+		t.commit();
+		t_checkNullLockCount(t);
+	}
+
+	/*
+	 * commit a transaction with context
+	 */
+	public void t_commit(T_TWC ctx) 
+		throws StandardException, T_Fail 
+	{
+		csFactory.setCurrentContextManager(ctx.cm);
+		try {
+		t_commit(ctx.tran);
+		} finally {
+			csFactory.resetCurrentContextManager(ctx.cm);
+		}
+	}
+
+	/*
+	 * close a transaction with context
+	 */
+	public void t_close(T_TWC ctx)
+		throws StandardException, T_Fail 
+	{
+		ctx.tran.close();
+		ctx.tran = null;
+		ctx.cm = null;		// no need to close a context ???
+	}
+
+	/*
+	 * abort a transaction
+	 */
+	public void t_abort(Transaction t) 
+		throws StandardException, T_Fail {
+		t.abort();
+		t_checkNullLockCount(t);
+	}
+
+	/*
+	 * abort a transaction with context
+	 */
+	public void t_abort(T_TWC ctx) 
+		throws StandardException, T_Fail 
+	{
+		csFactory.setCurrentContextManager(ctx.cm);
+		try {
+		t_abort(ctx.tran);
+		} finally {
+			csFactory.resetCurrentContextManager(ctx.cm);
+		}
+	}
+
+	/**
+		Add a new container in the transaction
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public long t_addContainer(Transaction t, long segmentId)
+		throws StandardException, T_Fail {
+		
+		long cid = 
+            t.addContainer(
+                segmentId, ContainerHandle.DEFAULT_ASSIGN_ID, 
+                ContainerHandle.MODE_DEFAULT, (Properties) null, 0);
+
+		if (cid < 0)
+			throw T_Fail.testFailMsg("add container");
+
+		return cid;		
+	}
+
+	public long t_addContainer(T_TWC ctx, long segmentId)
+		throws StandardException, T_Fail 
+	{
+		csFactory.setCurrentContextManager(ctx.cm);
+		try {
+		return t_addContainer(ctx.tran, segmentId);
+		} finally {
+			csFactory.resetCurrentContextManager(ctx.cm);
+		}
+	}
+
+	/**
+
+		Add a new container in the transaction with a specified page size
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public long t_addContainer(Transaction t, long segmentId, int pageSize)
+		throws StandardException, T_Fail {
+
+		Properties tableProperties = new Properties();
+		tableProperties.put(Property.PAGE_SIZE_PARAMETER, Integer.toString(pageSize));
+		
+		long cid = 
+            t.addContainer(
+                segmentId, ContainerHandle.DEFAULT_ASSIGN_ID, 
+                ContainerHandle.MODE_DEFAULT, tableProperties, 0);
+
+		if (cid < 0)
+			throw T_Fail.testFailMsg("add container");
+
+		return cid;		
+	}
+
+	public long t_addContainer(T_TWC ctx, long segmentId, int pageSize)
+		throws StandardException, T_Fail {
+
+		csFactory.setCurrentContextManager(ctx.cm);
+		try {
+		return t_addContainer(ctx.tran, segmentId, pageSize);
+		} finally {
+			csFactory.resetCurrentContextManager(ctx.cm);
+		}
+	}
+
+	public long t_addContainer(Transaction t, long segmentId, Properties tableProperties)
+		throws StandardException, T_Fail {
+
+		long cid = 
+            t.addContainer(
+                segmentId, ContainerHandle.DEFAULT_ASSIGN_ID, 
+                ContainerHandle.MODE_DEFAULT, tableProperties, 0);
+
+		if (cid < 0)
+			throw T_Fail.testFailMsg("add container");
+
+		return cid;		
+	}
+				
+
+	/**
+
+		Add a new container in the transaction with specified 
+        pageSize, spareSpace, minimumRecordSize, and reusableRecordId
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public long t_addContainer(Transaction t, long segmentId, int pageSize, int spareSpace, 
+			int minimumRecordSize, boolean reusableRecordId)
+		throws StandardException, T_Fail {
+
+		Properties tableProperties = new Properties();
+		tableProperties.put(Property.PAGE_SIZE_PARAMETER, Integer.toString(pageSize));
+		tableProperties.put(RawStoreFactory.PAGE_RESERVED_SPACE_PARAMETER, Integer.toString(spareSpace));
+		tableProperties.put(RawStoreFactory.MINIMUM_RECORD_SIZE_PARAMETER, Integer.toString(minimumRecordSize));
+
+        if (reusableRecordId) {
+            tableProperties.put(RawStoreFactory.PAGE_REUSABLE_RECORD_ID, "true");
+        }
+		
+		long cid = 
+            t.addContainer(
+                segmentId, ContainerHandle.DEFAULT_ASSIGN_ID, 
+                ContainerHandle.MODE_DEFAULT, tableProperties, 0);
+
+		if (cid < 0)
+			throw T_Fail.testFailMsg("add container");
+
+		return cid;		
+	}
+
+	public long t_addContainer(T_TWC ctx, long segmentId, int pageSize, int spareSpace, int minimumRecordSize)
+		throws StandardException, T_Fail {
+		csFactory.setCurrentContextManager(ctx.cm);
+		try {
+		return t_addContainer(ctx.tran, segmentId, pageSize, spareSpace, minimumRecordSize, false);
+		} finally {
+			csFactory.resetCurrentContextManager(ctx.cm);
+		}
+	}
+
+	/**
+		Open a container.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	
+	public ContainerHandle t_openContainer(Transaction t, long segmentId, long containerId, boolean forUpdate)
+		throws StandardException, T_Fail 
+	{
+		ContainerKey id = new ContainerKey(segmentId, containerId);
+		ContainerHandle c = t.openContainer(id,
+			forUpdate ? (ContainerHandle.MODE_FORUPDATE | openContainerMode) : ContainerHandle.MODE_READONLY);
+		if (c == null)
+			throw T_Fail.testFailMsg("ContainerHandle failed to open: (" +
+									 segmentId + "," + containerId + ")");
+
+		return c;
+	}
+	public ContainerHandle t_openContainer(T_TWC ctx, long segmentId, long containerId, boolean forUpdate)
+		throws StandardException, T_Fail 
+	{
+		csFactory.setCurrentContextManager(ctx.cm);
+		try {
+			return t_openContainer(ctx.tran, segmentId, containerId, forUpdate);
+		} finally {
+			csFactory.resetCurrentContextManager(ctx.cm);
+		}
+	}
+
+	/**
+		Drop a container 
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public void t_dropContainer(Transaction t, long segmentId, long containerId) 
+		 throws StandardException, T_Fail
+	{
+		t.dropContainer(new ContainerKey(segmentId, containerId));
+	}
+
+	/**
+		Get the last page in a container.
+		Always returns a valid page or null if there is no page in the container.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public Page t_getLastPage(ContainerHandle c) throws T_Fail, StandardException {
+
+		Page page = c.getFirstPage();
+		if (page != null)
+		{
+			Page nextPage;
+			while((nextPage = c.getNextPage(page.getPageNumber())) != null)
+			{
+				page.unlatch();
+				page = nextPage;
+			}
+		}
+
+		return page;
+	}
+
+
+	/**
+		Get a specific page in a container.
+		Always returns a valid page.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public Page t_getPage(ContainerHandle c, long pageNumber) throws T_Fail, StandardException {
+
+		Page page = c.getPage(pageNumber);
+		if (page == null)
+			throw T_Fail.testFailMsg("fail to get page " + pageNumber + " from container " + c);
+
+		if (page.getPageNumber() != pageNumber)
+			throw T_Fail.testFailMsg("page expected to have page number " +
+				pageNumber + ", has " + page.getPageNumber() + " Container " + c);
+
+		return page;
+	}
+
+	/**
+		Add a page to a container.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public Page t_addPage(ContainerHandle c) throws T_Fail, StandardException {
+
+		Page page = c.addPage();
+
+		if (page == null)
+			throw T_Fail.testFailMsg("addPage() returned null");
+
+		return page;
+	}
+
+	/**
+		Remove a page from a container.
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	public void t_removePage(ContainerHandle c, Page p) throws T_Fail, StandardException
+	{
+		long pnum = p.getPageNumber();
+		c.removePage(p);
+
+		// we should not be able to get this page 
+		Page badp = c.getPage(pnum);
+		if (badp != null)
+			throw T_Fail.testFailMsg("got a deallcated page back");
+	} 
+
+
+	/**
+		Call page.insert() and ensure that the return record handle is not null.
+		This assumes the caller has called spaceForInsert.
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#insert
+	*/
+	public static RecordHandle t_insert(Page page, T_RawStoreRow row)
+		throws T_Fail, StandardException {
+		
+		RecordHandle rh = page.insert(row.getRow(), (FormatableBitSet) null, Page.INSERT_DEFAULT, 100);
+
+		return rh;
+	}
+
+	/**
+		Call page.insert() and ensure that the return record handle is not null.
+		This assumes the caller has called spaceForInsert.
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#insert
+	*/
+	public static RecordHandle t_insertAtSlot(Page page, int slot, T_RawStoreRow row)
+		throws T_Fail, StandardException {
+		
+		RecordHandle rh = page.insertAtSlot(slot, row.getRow(), (FormatableBitSet) null,
+			(LogicalUndo) null, Page.INSERT_DEFAULT, 100);
+
+		return rh;
+	}
+
+	/**
+		Call page.insert() and ensure that the return record handle is not null.
+		This assumes the caller has called spaceForInsert.
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#insert
+	*/
+	public static RecordHandle t_insertAtSlot(Page page, int slot, T_RawStoreRow row, byte insertFlag)
+		throws T_Fail, StandardException {
+		
+		RecordHandle rh = page.insertAtSlot(slot, row.getRow(), (FormatableBitSet) null,
+			(LogicalUndo) null, insertFlag, 100);
+
+		return rh;
+	}
+
+	/**
+		Call page.insert() and ensure that the return record handle is not null.
+		This assumes the caller has called spaceForInsert.
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#insert
+	*/
+	public static RecordHandle t_insertAtSlot(Page page, int slot, T_RawStoreRow row, byte insertFlag,
+			int overflowThreshold) throws T_Fail, StandardException {
+		
+		RecordHandle rh = page.insertAtSlot(slot, row.getRow(), (FormatableBitSet) null,
+			(LogicalUndo) null, insertFlag, overflowThreshold);
+
+		return rh;
+	}
+
+	/**
+		Insert a record on the last page, if the row doesn't fit on the
+		last page create a new page and insert there.
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#insert
+	*/
+	public RecordHandle t_insert(ContainerHandle c, T_RawStoreRow row)
+		throws T_Fail, StandardException {
+
+		Page page = c.getPageForInsert(0);
+		boolean addedPage = false;
+
+		if (page == null)
+		{
+			page = t_addPage(c);
+			addedPage = true;
+		}
+		else if (!page.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100)) {
+			page.unlatch();
+			page = t_addPage(c);
+			addedPage = true;
+		}
+
+		RecordHandle rh = t_insert(page, row);
+		page.unlatch();
+
+		if (rh == null) {
+			if (addedPage)
+				throw T_Fail.testFailMsg("insert returned null on an empty page");
+
+			page = t_addPage(c);
+			rh = t_insert(page, row);
+			page.unlatch();
+		}
+		return rh;
+	}
+
+	/**
+		Update a record.
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#update
+	*/
+	public void t_update(ContainerHandle c, RecordHandle rh, T_RawStoreRow row)
+		 throws T_Fail, StandardException
+	{
+		Page page = t_getPage(c, rh.getPageNumber());
+		try
+		{
+			if (!page.update(rh, row.getRow(), (FormatableBitSet)null))
+				throw T_Fail.testFailMsg("update failed");
+
+			t_checkFetch(page, rh, row);
+		}
+		finally
+		{
+			page.unlatch();
+		}
+	}
+
+
+
+	/**
+	    Using sparse representation:
+		Update a column of a record and check resulting value.
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#update
+	*/
+	public void t_checkUpdateCol(Page page, RecordHandle rh, int colNum, int
+								 numCols, String data)
+		 throws T_Fail, StandardException
+	{
+		if (!page.recordExists(rh, false))
+			throw T_Fail.testFailMsg("Record does not exist");
+
+		T_RawStoreRow writeRow = new T_RawStoreRow(numCols);
+		for (int i = 0; i < numCols; i++)	
+			writeRow.setColumn(i, (String) null);
+		writeRow.setColumn(colNum, data);
+		FormatableBitSet colList = new FormatableBitSet(numCols);
+		colList.set(colNum);
+
+		if (!page.update(rh, writeRow.getRow(), colList))
+			throw T_Fail.testFailMsg("update failed");
+		
+		t_checkFetchCol(page, rh, colNum, numCols, data);
+	}
+
+        
+
+	/**
+		Delete a record.
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#delete
+	*/
+	public void t_delete(ContainerHandle c, RecordHandle rh)
+		throws T_Fail, StandardException {
+
+		Page page = t_getPage(c, rh.getPageNumber());
+
+		try
+		{
+			if (!page.recordExists(rh, false))
+				throw T_Fail.testFailMsg("record does not exist");
+
+			if (!page.delete(rh, (LogicalUndo)null))
+				throw T_Fail.testFailMsg("delete failed");
+
+			if (page.recordExists(rh, false))
+				throw T_Fail.testFailMsg("recordExists() returns true after a delete");
+		}
+		finally
+		{
+			page.unlatch();
+		}
+	}
+
+	/**
+		Check to make sure a row (possibly with overflow) is of the correct length
+
+		@exception T_Fail Record handle returned is null.
+		@exception StandardException Unexpected exception from the implementation
+
+	 */
+	public void t_checkStringLengthFetch(Page page, int slot, int expectedLength) throws T_Fail, StandardException {
+
+		T_RawStoreRow rr = new T_RawStoreRow((String) null);
+
+		page.fetchFromSlot(
+            (RecordHandle) null, slot, rr.getRow(), 
+            (FetchDescriptor) null,
+            true);
+
+		String s = ((SQLChar) (rr.getStorableColumn(0))).getString();
+
+
+		if ((s == null) && (expectedLength < 0))
+			return;
+
+		if ((s != null) && (expectedLength < 0))
+			throw T_Fail.testFailMsg("Expected null string, fetched one of length " + s.length());
+
+		if (s == null)
+			throw T_Fail.testFailMsg("Expected string length " + expectedLength + " got null string");
+
+		if (s.length() != expectedLength)
+			throw T_Fail.testFailMsg("fetch string length incorrect expected " + expectedLength + " got " + s.length());
+	}
+
+	/**
+		Lazy people's random file generator:
+		Generate a random file with specified name and file size
+
+		@exception T_Fail Record handle returned is null.
+	*/
+	public void t_genRandomFile(String fileName, String mode, int size) throws T_Fail {
+
+		RandomAccessFile iFile = null;
+		try {
+			iFile = new RandomAccessFile(fileName, mode);
+			for (int i = 0; i < size; i++){
+				byte b = (byte) (i & 0xff);
+				b = (byte) (((b >= ' ') && (b <= '~')) ? b : ' ');
+				iFile.write(b);
+			}
+			iFile.close();
+		} catch (FileNotFoundException fnfe) {
+			throw T_Fail.testFailMsg("cannot create new file");
+		} catch (IOException ioe) {
+			throw T_Fail.testFailMsg("io error, test failed");
+		}
+
+	}
+
+	/**
+		Return a string of stringLen characters that starts with data
+		and is padded with nulls.
+	*/
+	public static String getStringFromData(String data, int stringLen) {
+		char[] ca = new char[stringLen];
+
+		char[] sd = data.toCharArray();
+
+		System.arraycopy(sd, 0, ca, 0, sd.length);
+		
+		return new String(ca);
+	}
+
+	/**
+		Make this thread wait a bit, probably for post commit to finish
+	 */
+	public static void t_wait(int milliSecond)
+	{
+		Thread.currentThread().yield();
+		try
+		{
+			Thread.currentThread().sleep(milliSecond);
+		}
+		catch (InterruptedException ie)
+		{
+		}
+	}
+
+	/**
+		Add in encryption parameters to the startParam if "testDataEncryption"
+		is set to a non-null string.
+	 */
+	public static Properties setEncryptionParam(Properties startParams)
+	{
+		// see if we are testing encryption
+		String encryptionPassword = 
+					PropertyUtil.getSystemProperty("testDataEncryption");
+		//look for alternate encryption provider
+		String encryptionProvider = 
+					PropertyUtil.getSystemProperty("testEncryptionProvider");
+		if (encryptionPassword != null)
+		{
+			if (startParams == null)
+				startParams = new Properties();
+
+			startParams.put(Attribute.DATA_ENCRYPTION, "true");
+			startParams.put(Attribute.BOOT_PASSWORD, encryptionPassword);
+			if (encryptionProvider != null) {
+			    startParams.put(Attribute.CRYPTO_PROVIDER, encryptionProvider);
+			}
+
+			//			System.out.println("Setting encryption password to " + encryptionPassword);
+
+		}
+
+		return startParams;
+	}
+
+}

Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_Util.java
------------------------------------------------------------------------------
    snv:eol-style = native

Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_XA.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_XA.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_XA.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_XA.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,1277 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_XA
+
+   Copyright 1999, 2005 The Apache Software Foundation or its licensors, as applicable.
+
+   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.derbyTesting.unitTests.store;
+
+import org.apache.derbyTesting.unitTests.harness.T_Generic;
+import org.apache.derbyTesting.unitTests.harness.T_Fail;
+
+import org.apache.derby.iapi.store.access.xa.*;
+import org.apache.derby.iapi.store.access.*;
+
+import org.apache.derby.iapi.services.io.FormatableBitSet;
+
+import org.apache.derby.iapi.reference.Property;
+
+import org.apache.derby.iapi.services.context.ContextService;
+import org.apache.derby.iapi.services.context.ContextManager;
+
+import org.apache.derby.iapi.services.monitor.Monitor;
+
+import org.apache.derby.iapi.services.sanity.SanityManager;
+
+import org.apache.derby.iapi.services.io.FormatIdUtil;
+
+import org.apache.derby.iapi.error.StandardException; 
+
+import java.util.Properties; 
+
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+
+
+public class T_XA extends T_Generic
+{
+    private static final String testService = "XaTest";
+
+    byte[] global_id = 
+        { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+         10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+         20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+         30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+         40, 41, 42, 44, 44, 45, 46, 47, 48, 49,
+         50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+         60, 61, 62, 63};
+
+    byte[] branch_id = 
+        { 0,  1,  2,  3,  4,  5,  6,  7,  8,  9,
+         10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+         20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
+         30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
+         40, 41, 42, 44, 44, 45, 46, 47, 48, 49,
+         50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+         60, 61, 62, 63};
+
+    AccessFactory store = null;
+
+	public T_XA()
+    {
+		super();
+	}
+
+	/*
+	** Methods of UnitTest.
+	*/
+
+	/*
+	** Methods required by T_Generic
+	*/
+
+	public String getModuleToTestProtocolName()
+    {
+		return AccessFactory.MODULE;
+	}
+
+	/**
+		@exception T_Fail Unexpected behaviour from the API
+	 */
+
+	protected void runTests() throws T_Fail
+	{
+		// Create a AccessFactory to test.
+
+		// don't automatic boot this service if it gets left around
+		if (startParams == null) 
+        {
+			startParams = new Properties();
+		}
+		startParams.put(Property.NO_AUTO_BOOT, Boolean.TRUE.toString());
+		// remove the service directory to ensure a clean run
+		startParams.put(Property.DELETE_ON_CREATE, Boolean.TRUE.toString());
+
+		// see if we are testing encryption
+		startParams = T_Util.setEncryptionParam(startParams);
+
+		try {
+			store = (AccessFactory) Monitor.createPersistentService(
+				getModuleToTestProtocolName(), testService, startParams);
+		} catch (StandardException mse) {
+			throw T_Fail.exceptionFail(mse);
+		}
+
+
+		if (store == null) 
+        {
+			throw T_Fail.testFailMsg(
+                getModuleToTestProtocolName() + " service not started.");
+		}
+
+		REPORT("(unitTestMain) Testing " + testService);
+
+		try {
+
+            XATest_1(new commit_method(store, true));
+            XATest_2(new commit_method(store, true));
+            XATest_3(new commit_method(store, true));
+            XATest_4(new commit_method(store, true));
+            XATest_5(new commit_method(store, true));
+            XATest_6(new commit_method(store, true));
+
+            XATest_1(new commit_method(store, false));
+            XATest_2(new commit_method(store, false));
+            XATest_3(new commit_method(store, false));
+            XATest_4(new commit_method(store, false));
+            XATest_5(new commit_method(store, false));
+            XATest_6(new commit_method(store, false));
+		}
+		catch (StandardException e)
+		{
+			String  msg = e.getMessage();
+			if (msg == null)
+				msg = e.getClass().getName();
+			REPORT(msg);
+            e.printStackTrace();
+			throw T_Fail.exceptionFail(e);
+		}
+        catch (Throwable t)
+        {
+            t.printStackTrace();
+        }
+	}
+
+    /**************************************************************************
+     * Utility methods.
+     **************************************************************************
+     */
+
+    /**************************************************************************
+     * Test Cases.
+     **************************************************************************
+     */
+
+    /**
+     * one phase commit xa transaction.
+     * <p>
+	 * @exception  StandardException  Standard exception policy.
+     **/
+    void XATest_1(
+    commit_method   commit_method)
+        throws StandardException, T_Fail
+    {
+        REPORT("(XATest_1) starting");
+
+        ContextManager cm = 
+                ContextService.getFactory().getCurrentContextManager();
+
+        // COMMIT AN IDLE TRANSACTION.
+
+        // Start a global transaction
+        XATransactionController xa_tc = (XATransactionController) 
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.commit(true, 42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // COMMIT AN UPDATE ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Create a heap conglomerate.
+        T_AccessRow template_row = new T_AccessRow(1);
+		long conglomid = 
+            xa_tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+				null,  	//column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.commit(true, 42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // COMMIT A READ ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Open a scan on the conglomerate.
+		ScanController scan1 = xa_tc.openScan(
+			conglomid,
+			false, // don't hold
+			0,     // not for update
+            TransactionController.MODE_RECORD,
+            TransactionController.ISOLATION_SERIALIZABLE,
+			(FormatableBitSet) null, // all columns, all as objects
+			null, // start position - first row in conglomerate
+            0,    // unused if start position is null.
+			null, // qualifier - accept all rows
+			null, // stop position - last row in conglomerate
+            0);   // unused if stop position is null.
+
+        scan1.next();
+        scan1.close();
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.commit(true, 42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        REPORT("(XATest_1) finishing");
+    }
+
+    /**
+     * simple two phase commit xa transaction.
+     * <p>
+	 * @exception  StandardException  Standard exception policy.
+     **/
+    void XATest_2(
+    commit_method   commit_method)
+        throws StandardException, T_Fail
+    {
+        REPORT("(XATest_2) starting");
+        ContextManager cm = 
+                ContextService.getFactory().getCurrentContextManager();
+
+        // COMMIT AN IDLE TRANSACTION.
+
+        // Start a global transaction
+        XATransactionController xa_tc = (XATransactionController) 
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+        if (!xa_tc.isGlobal())
+        {
+			throw T_Fail.testFailMsg("should be a global transaction.");
+        }
+
+        // This prepare will commit the idle transaction.
+        if (xa_tc.xa_prepare() != XATransactionController.XA_RDONLY)
+        {
+			throw T_Fail.testFailMsg(
+                "prepare of idle xact did not return XA_RDONLY.");
+        }
+
+        // commit an idle transaction - using onePhase optimization.
+        try 
+        {
+            // this should fail as the xact has been committed, so committing
+            // it in 2 phase mode should fail.  This test can't be run in 
+            // offline mode, no transaction will be found.  Pass null as
+            // global_id to make that test not run.
+
+            commit_method.commit(false, 42, null, null, xa_tc);
+
+			throw T_Fail.testFailMsg(
+                "A XA_RDONLY prepare-committed xact cant be 2P xa_committed.");
+        }
+        catch (StandardException se)
+        {
+            // expected exception - drop through.
+        }
+
+        // should not be able to find this global xact, it has been committed
+        if (((XAResourceManager) store.getXAResourceManager()).find(
+                new XAXactId(42, global_id, branch_id)) != null)
+        {
+			throw T_Fail.testFailMsg(
+                "A XA_RDONLY prepare-committed xact should not be findable.");
+        }
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // COMMIT AN UPDATE ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Create a heap conglomerate.
+        T_AccessRow template_row = new T_AccessRow(1);
+		long conglomid = 
+            xa_tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+                null, 	//column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+        // prepare the update xact.
+        if (xa_tc.xa_prepare() != XATransactionController.XA_OK)
+        {
+			throw T_Fail.testFailMsg(
+                "prepare of update xact did not return XA_OK.");
+        }
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.commit(false, 42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // COMMIT A READ ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Open a scan on the conglomerate.
+		ScanController scan1 = xa_tc.openScan(
+			conglomid,
+			false, // don't hold
+			0,     // not for update
+            TransactionController.MODE_RECORD,
+            TransactionController.ISOLATION_SERIALIZABLE,
+			(FormatableBitSet) null, // all columns, all as objects
+			null, // start position - first row in conglomerate
+            0,    // unused if start position is null.
+			null, // qualifier - accept all rows
+			null, // stop position - last row in conglomerate
+            0);   // unused if stop position is null.
+
+        scan1.next();
+        scan1.close();
+
+        // This prepare will commit the idle transaction.
+        if (xa_tc.xa_prepare() != XATransactionController.XA_RDONLY)
+        {
+			throw T_Fail.testFailMsg(
+                "prepare of idle xact did not return XA_RDONLY.");
+        }
+
+        // commit an idle transaction - using onePhase optimization.
+        try 
+        {
+            // this should fail as the xact has been committed, so committing
+            // it in 2 phase mode should fail.  This test can't be run in 
+            // offline mode, no transaction will be found.  Pass null as
+            // global_id to make that test not run.
+
+            commit_method.commit(false, 42, null, null, xa_tc);
+
+			throw T_Fail.testFailMsg(
+                "A XA_RDONLY prepare-committed xact cant be 2P xa_committed.");
+        }
+        catch (StandardException se)
+        {
+            // expected exception - drop through.
+        }
+
+        // should not be able to find this global xact, it has been committed
+        if (((XAResourceManager) store.getXAResourceManager()).find(
+                new XAXactId(42, global_id, branch_id)) != null)
+        {
+			throw T_Fail.testFailMsg(
+                "A XA_RDONLY prepare-committed xact should not be findable.");
+        }
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        REPORT("(XATest_2) finishing");
+    }
+
+    /**
+     * Test aborts of unprepared xa transaction.
+     * <p>
+	 * @exception  StandardException  Standard exception policy.
+     **/
+    void XATest_3(
+    commit_method   commit_method)
+        throws StandardException, T_Fail
+    {
+        REPORT("(XATest_3) starting");
+
+        ContextManager cm = 
+                ContextService.getFactory().getCurrentContextManager();
+
+        // ABORT AN IDLE TRANSACTION.
+
+        // Start a global transaction
+        XATransactionController xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.rollback(42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // ABORT AN UPDATE ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Create a heap conglomerate.
+        T_AccessRow template_row = new T_AccessRow(1);
+		long conglomid = 
+            xa_tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+				null, //column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.rollback(42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // ABORT A READ ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Create a heap conglomerate.
+        template_row = new T_AccessRow(1);
+		conglomid = 
+            xa_tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+				null, //column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.commit(true, 42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Open a scan on the conglomerate.
+		ScanController scan1 = xa_tc.openScan(
+			conglomid,
+			false, // don't hold
+			0,     // not for update
+            TransactionController.MODE_RECORD,
+            TransactionController.ISOLATION_SERIALIZABLE,
+			(FormatableBitSet) null, // all columns, all as objects
+			null, // start position - first row in conglomerate
+            0,    // unused if start position is null.
+			null, // qualifier - accept all rows
+			null, // stop position - last row in conglomerate
+            0);   // unused if stop position is null.
+
+        scan1.next();
+        scan1.close();
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.rollback(42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        REPORT("(XATest_3) finishing");
+    }
+
+    /**
+     * Test aborts of prepared two phase commit xa transaction.
+     * <p>
+	 * @exception  StandardException  Standard exception policy.
+     **/
+    void XATest_4(
+    commit_method   commit_method)
+        throws StandardException, T_Fail
+    {
+        REPORT("(XATest_4) starting");
+
+        ContextManager cm = 
+                ContextService.getFactory().getCurrentContextManager();
+
+        // ABORT AN IDLE TRANSACTION.
+
+        // Start a global transaction
+        XATransactionController xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+        // This prepare will commit the idle transaction.
+        if (xa_tc.xa_prepare() != XATransactionController.XA_RDONLY)
+        {
+			throw T_Fail.testFailMsg(
+                "prepare of idle xact did not return XA_RDONLY.");
+        }
+
+        // nothing to do, will just abort the next current idle xact.
+
+       // after prepare/readonly we cna continue to use transaction   
+		commit_method.commit(true, 42, null, null, xa_tc);
+
+
+
+        // should not be able to find this global xact, it has been committed
+        if (((XAResourceManager) store.getXAResourceManager()).find(
+                new XAXactId(42, global_id, branch_id)) != null)
+        {
+			throw T_Fail.testFailMsg(
+                "A XA_RDONLY prepare-committed xact should not be findable.");
+        }
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // ABORT AN UPDATE ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Create a heap conglomerate.
+        T_AccessRow template_row = new T_AccessRow(1);
+		long conglomid = 
+            xa_tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+				null, //column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+
+
+        // Open a scan on the conglomerate, to verify the create happened,
+        // and to show that the same openScan done after abort fails.
+        ScanController scan1 = xa_tc.openScan(
+            conglomid,
+            false, // don't hold
+            0,     // not for update
+            TransactionController.MODE_RECORD,
+            TransactionController.ISOLATION_SERIALIZABLE,
+            (FormatableBitSet) null, // all columns, all as objects
+            null, // start position - first row in conglomerate
+            0,    // unused if start position is null.
+            null, // qualifier - accept all rows
+            null, // stop position - last row in conglomerate
+            0);   // unused if stop position is null.
+
+        scan1.next();
+        scan1.close();
+
+        // prepare the update xact.
+        if (xa_tc.xa_prepare() != XATransactionController.XA_OK)
+        {
+			throw T_Fail.testFailMsg(
+                "prepare of update xact did not return XA_OK.");
+        }
+
+        try
+        {
+            // Open a scan on the conglomerate.
+            scan1 = xa_tc.openScan(
+                conglomid,
+                false, // don't hold
+                0,     // not for update
+                TransactionController.MODE_RECORD,
+                TransactionController.ISOLATION_SERIALIZABLE,
+                (FormatableBitSet) null, // all columns, all as objects
+                null, // start position - first row in conglomerate
+                0,    // unused if start position is null.
+                null, // qualifier - accept all rows
+                null, // stop position - last row in conglomerate
+                0);   // unused if stop position is null.
+
+            scan1.next();
+            scan1.close();
+
+			throw T_Fail.testFailMsg(
+                "Should not be able to do anything on xact after prepare.");
+        }
+        catch (StandardException se)
+        {
+            // expected exception, fall through.
+        }
+
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.rollback(42, global_id, branch_id, xa_tc);
+
+        commit_method.commit(true, 42, null, null, xa_tc);
+
+        // should not be able to find this global xact, it has been committed
+        if (((XAResourceManager) store.getXAResourceManager()).find(
+                new XAXactId(42, global_id, branch_id)) != null)
+        {
+			throw T_Fail.testFailMsg(
+                "A xa_rollbacked xact should not be findable.");
+        }
+
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+        try
+        {
+            // Open a scan on the conglomerate.
+            scan1 = xa_tc.openScan(
+                conglomid,
+                false, // don't hold
+                0,     // not for update
+                TransactionController.MODE_RECORD,
+                TransactionController.ISOLATION_SERIALIZABLE,
+                (FormatableBitSet) null, // all columns, all as objects
+                null, // start position - first row in conglomerate
+                0,    // unused if start position is null.
+                null, // qualifier - accept all rows
+                null, // stop position - last row in conglomerate
+                0);   // unused if stop position is null.
+
+            scan1.next();
+            scan1.close();
+
+			throw T_Fail.testFailMsg(
+                "Should not be able to open conglom, the create was aborted.");
+        }
+        catch (StandardException se)
+        {
+            // expected exception, fall through.
+        }
+
+        xa_tc.destroy();
+
+
+        // ABORT A READ ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Create a heap conglomerate.
+        template_row = new T_AccessRow(1);
+		conglomid = 
+            xa_tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+				null, //column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+        commit_method.commit(true, 42, global_id, branch_id, xa_tc);
+
+        xa_tc.destroy();
+
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Open a scan on the conglomerate.
+		scan1 = xa_tc.openScan(
+			conglomid,
+			false, // don't hold
+			0,     // not for update
+            TransactionController.MODE_RECORD,
+            TransactionController.ISOLATION_SERIALIZABLE,
+			(FormatableBitSet) null, // all columns, all as objects
+			null, // start position - first row in conglomerate
+            0,    // unused if start position is null.
+			null, // qualifier - accept all rows
+			null, // stop position - last row in conglomerate
+            0);   // unused if stop position is null.
+
+        scan1.next();
+        scan1.close();
+
+        // This prepare will commit the idle transaction.
+        if (xa_tc.xa_prepare() != XATransactionController.XA_RDONLY)
+        {
+			throw T_Fail.testFailMsg(
+                "prepare of idle xact did not return XA_RDONLY.");
+        }
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.commit(true, 42, null, null, xa_tc);
+
+        // should not be able to find this global xact, it has been committed
+        if (((XAResourceManager) store.getXAResourceManager()).find(
+                new XAXactId(42, global_id, branch_id)) != null)
+        {
+			throw T_Fail.testFailMsg(
+                "A XA_RDONLY prepare-committed xact should not be findable.");
+        }
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        REPORT("(XATest_5) finishing");
+    }
+
+    /**
+     * Very simple testing of the recover() call.
+     * <p>
+	 * @exception  StandardException  Standard exception policy.
+     **/
+    void XATest_5(
+    commit_method   commit_method)
+        throws StandardException, T_Fail
+    {
+        REPORT("(XATest_5) starting");
+
+        // Should be no prepared transactions when we first start.
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMSTARTRSCAN).length != 0)
+        {
+			throw T_Fail.testFailMsg(
+                "recover incorrectly returned prepared xacts.");
+        }
+
+        // Should be no prepared transactions when we first start.
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMNOFLAGS).length != 0)
+        {
+			throw T_Fail.testFailMsg("NOFLAGS should always return 0.");
+        }
+
+        ContextManager cm = 
+                ContextService.getFactory().getCurrentContextManager();
+
+        // COMMIT AN IDLE TRANSACTION.
+
+        // Start a global transaction
+        XATransactionController xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+        // Should be no prepared transactions, there is one idle global xact.
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMSTARTRSCAN).length != 0)
+        {
+			throw T_Fail.testFailMsg(
+                "recover incorrectly returned prepared xacts.");
+        }
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.commit(true, 42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // COMMIT AN UPDATE ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Create a heap conglomerate.
+        T_AccessRow template_row = new T_AccessRow(1);
+		long conglomid = 
+            xa_tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+				null, //column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+        // Should be no prepared transactions, there is one update global xact.
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMSTARTRSCAN).length != 0)
+        {
+			throw T_Fail.testFailMsg(
+                "recover incorrectly returned prepared xacts.");
+        }
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.commit(true, 42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // COMMIT A READ ONLY TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Open a scan on the conglomerate.
+		ScanController scan1 = xa_tc.openScan(
+			conglomid,
+			false, // don't hold
+			0,     // not for update
+            TransactionController.MODE_RECORD,
+            TransactionController.ISOLATION_SERIALIZABLE,
+			(FormatableBitSet) null, // all columns, all as objects
+			null, // start position - first row in conglomerate
+            0,    // unused if start position is null.
+			null, // qualifier - accept all rows
+			null, // stop position - last row in conglomerate
+            0);   // unused if stop position is null.
+
+        scan1.next();
+        scan1.close();
+
+        // Should be no prepared transactions, there is one update global xact.
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMSTARTRSCAN).length != 0)
+        {
+			throw T_Fail.testFailMsg(
+                "recover incorrectly returned prepared xacts.");
+        }
+
+
+        // commit an idle transaction - using onePhase optimization.
+        commit_method.commit(true, 42, global_id, branch_id, xa_tc);
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // PREPARE AN UPDATE TRANSACTION.
+
+        // Start a global transaction
+        xa_tc = (XATransactionController)
+            store.startXATransaction(
+                cm,
+                42, // fake format id
+                global_id,
+                branch_id);
+
+		// Create a heap conglomerate.
+        template_row = new T_AccessRow(1);
+		conglomid = 
+            xa_tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+				null, //column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+        // Should be no prepared transactions, there is one update global xact.
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMSTARTRSCAN).length != 0)
+        {
+			throw T_Fail.testFailMsg(
+                "recover incorrectly returned prepared xacts.");
+        }
+
+        // prepare the update xact.
+        if (xa_tc.xa_prepare() != XATransactionController.XA_OK)
+        {
+			throw T_Fail.testFailMsg(
+                "prepare of update xact did not return XA_OK.");
+        }
+
+        try
+        {
+            // Open a scan on the conglomerate.
+            scan1 = xa_tc.openScan(
+                conglomid,
+                false, // don't hold
+                0,     // not for update
+                TransactionController.MODE_RECORD,
+                TransactionController.ISOLATION_SERIALIZABLE,
+                (FormatableBitSet) null, // all columns, all as objects
+                null, // start position - first row in conglomerate
+                0,    // unused if start position is null.
+                null, // qualifier - accept all rows
+                null, // stop position - last row in conglomerate
+                0);   // unused if stop position is null.
+
+            scan1.next();
+            scan1.close();
+
+			throw T_Fail.testFailMsg(
+                "Should not be able to do anything on xact after prepare.");
+        }
+        catch (StandardException se)
+        {
+            // expected exception, fall through.
+        }
+
+        // Should be no prepared transactions, there is one update global xact.
+        Xid[] prepared_xacts = 
+            ((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMSTARTRSCAN);
+
+        if (prepared_xacts.length != 1)
+        {
+			throw T_Fail.testFailMsg(
+                "recover incorrectly returned wrong prepared xacts.");
+        }
+
+        if (prepared_xacts[0].getFormatId() != 42)
+			throw T_Fail.testFailMsg(
+                "bad format id = " + prepared_xacts[0].getFormatId());
+
+        byte[] gid = prepared_xacts[0].getGlobalTransactionId();
+
+        if (!java.util.Arrays.equals(gid, global_id))
+        {
+			throw T_Fail.testFailMsg(
+                "bad global id = " + org.apache.derbyTesting.unitTests.util.BitUtil.hexDump(gid));
+        }
+
+        byte[] bid = prepared_xacts[0].getBranchQualifier();
+
+        if (!java.util.Arrays.equals(bid, branch_id))
+        {
+			throw T_Fail.testFailMsg(
+                "bad branch id = " + org.apache.derbyTesting.unitTests.util.BitUtil.hexDump(bid));
+        }
+
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMNOFLAGS).length != 0)
+        {
+			throw T_Fail.testFailMsg("NOFLAGS should always return 0.");
+        }
+
+        // commit a prepared transaction - using two phase.
+        commit_method.commit(false, 42, global_id, branch_id, xa_tc);
+
+        // Should be no prepared transactions, there is one update global xact.
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMSTARTRSCAN).length != 0)
+        {
+			throw T_Fail.testFailMsg(
+                "recover incorrectly returned prepared xacts.");
+        }
+
+        // done with this xact.
+        xa_tc.destroy();
+
+        // Should be no prepared transactions, there is one update global xact.
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMSTARTRSCAN).length != 0)
+        {
+			throw T_Fail.testFailMsg(
+                "recover incorrectly returned prepared xacts.");
+        }
+
+        REPORT("(XATest_5) finishing");
+
+    }
+
+    /**
+     * Very simple testing of changing a local transaction to a global.
+     * <p>
+	 * @exception  StandardException  Standard exception policy.
+     **/
+    void XATest_6(
+    commit_method   commit_method)
+        throws StandardException, T_Fail
+    {
+        REPORT("(XATest_5) starting");
+
+        ContextManager cm = 
+                ContextService.getFactory().getCurrentContextManager();
+
+        TransactionController   tc = store.getTransaction(cm);
+
+		// Create a heap conglomerate.
+        T_AccessRow template_row = new T_AccessRow(1);
+		long conglomid = 
+            tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+				null, //column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+        tc.commit();
+
+        // COMMIT AN IDLE TRANSACTION.
+
+        // Start a global transaction
+        XATransactionController xa_tc = (XATransactionController)
+            tc.createXATransactionFromLocalTransaction(
+                42, // fake format id
+                global_id,
+                branch_id);
+
+        if (!xa_tc.isGlobal())
+        {
+			throw T_Fail.testFailMsg("should be a global transaction.");
+        }
+
+
+		// Open a scan on the conglomerate.
+		ScanController scan1 = xa_tc.openScan(
+			conglomid,
+			false, // don't hold
+			0,     // not for update
+            TransactionController.MODE_RECORD,
+            TransactionController.ISOLATION_SERIALIZABLE,
+			(FormatableBitSet) null, // all columns, all as objects
+			null, // start position - first row in conglomerate
+            0,    // unused if start position is null.
+			null, // qualifier - accept all rows
+			null, // stop position - last row in conglomerate
+            0);   // unused if stop position is null.
+
+
+        scan1.next();
+        scan1.close();
+
+
+		// Create a heap conglomerate.
+        template_row = new T_AccessRow(1);
+		conglomid = 
+            xa_tc.createConglomerate(
+                "heap",       // create a heap conglomerate
+                template_row.getRowArray(), // 1 column template.
+				null, //column sort order - not required for heap
+                null,         // default properties
+                TransactionController.IS_DEFAULT);       // not temporary
+
+        // Should be no prepared transactions, there is one update global xact.
+        if (((XAResourceManager) store.getXAResourceManager()).recover(
+                XAResource.TMSTARTRSCAN).length != 0)
+        {
+			throw T_Fail.testFailMsg(
+                "recover incorrectly returned prepared xacts.");
+        }
+
+        // prepare the update xact.
+        if (xa_tc.xa_prepare() != XATransactionController.XA_OK)
+        {
+			throw T_Fail.testFailMsg(
+                "prepare of update xact did not return XA_OK.");
+        }
+
+        try
+        {
+            // Open a scan on the conglomerate.
+            scan1 = xa_tc.openScan(
+                conglomid,
+                false, // don't hold
+                0,     // not for update
+                TransactionController.MODE_RECORD,
+                TransactionController.ISOLATION_SERIALIZABLE,
+                (FormatableBitSet) null, // all columns, all as objects
+                null, // start position - first row in conglomerate
+                0,    // unused if start position is null.
+                null, // qualifier - accept all rows
+                null, // stop position - last row in conglomerate
+                0);   // unused if stop position is null.
+
+            scan1.next();
+            scan1.close();
+
+			throw T_Fail.testFailMsg(
+                "Should not be able to do anything on xact after prepare.");
+        }
+        catch (StandardException se)
+        {
+            // expected exception, fall through.
+        }
+
+        // commit a prepared transaction - using two phase.
+        commit_method.commit(false, 42, global_id, branch_id, xa_tc);
+
+        xa_tc.destroy();
+
+        REPORT("(XATest_6) finishing");
+    }
+
+}
+
+class commit_method
+{
+    private boolean         online_xact;
+    private AccessFactory   store;
+
+    public commit_method(
+    AccessFactory   store,
+    boolean         online_xact)
+    {
+        this.store       = store;
+        this.online_xact = online_xact;
+    }
+
+    public void commit(
+    boolean                 one_phase,
+    int                     format_id,
+    byte[]                  global_id,
+    byte[]                  branch_id,
+    XATransactionController xa_tc)
+        throws StandardException
+    {
+        if (SanityManager.DEBUG)
+            SanityManager.ASSERT((global_id != null) || (xa_tc != null));
+
+        boolean local_online_xact = online_xact;
+
+        if (global_id == null)
+            local_online_xact = true;
+        if (xa_tc == null)
+            local_online_xact = false;
+            
+        if (local_online_xact)
+        {
+            xa_tc.xa_commit(one_phase);
+        }
+        else
+        {
+            Xid xid = new XAXactId(format_id, global_id, branch_id);
+
+            ContextManager cm = 
+                ((XAResourceManager) store.getXAResourceManager()).find(xid);
+
+            if (SanityManager.DEBUG)
+            {
+                SanityManager.ASSERT(cm != null, "could not find xid = " + xid);
+
+                SanityManager.ASSERT(
+                    cm == 
+                    ContextService.getFactory().getCurrentContextManager(),
+                    "cm = " + cm +
+                    "current = " + 
+                        ContextService.getFactory().getCurrentContextManager());
+            }
+
+            ((XAResourceManager) store.getXAResourceManager()).commit(
+                cm, xid, one_phase);
+        }
+    }
+
+    public void rollback(
+    int                     format_id,
+    byte[]                  global_id,
+    byte[]                  branch_id,
+    XATransactionController xa_tc)
+        throws StandardException
+    {
+        if (SanityManager.DEBUG)
+            SanityManager.ASSERT((global_id != null) || (xa_tc != null));
+
+        boolean local_online_xact = online_xact;
+
+        if (global_id == null)
+            local_online_xact = true;
+        if (xa_tc == null)
+            local_online_xact = false;
+            
+        if (local_online_xact)
+        {
+            xa_tc.xa_rollback();
+        }
+        else
+        {
+            Xid xid = new XAXactId(format_id, global_id, branch_id);
+
+            ContextManager cm = 
+                ((XAResourceManager) store.getXAResourceManager()).find(xid);
+
+            if (SanityManager.DEBUG)
+            {
+                SanityManager.ASSERT(cm != null, "could not find xid = " + xid);
+
+                SanityManager.ASSERT(
+                    cm == 
+                    ContextService.getFactory().getCurrentContextManager(),
+                    "cm = " + cm +
+                    "current = " + 
+                        ContextService.getFactory().getCurrentContextManager());
+            }
+
+            ((XAResourceManager) store.getXAResourceManager()).rollback(
+                cm, xid);
+        }
+    }
+}

Propchange: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_XA.java
------------------------------------------------------------------------------
    snv:eol-style = native



Mime
View raw message