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 [9/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:46 GMT
Added: incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_RawStoreFactory.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_RawStoreFactory.java?view=auto&rev=155990
==============================================================================
--- incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_RawStoreFactory.java (added)
+++ incubator/derby/code/trunk/java/testing/org/apache/derbyTesting/unitTests/store/T_RawStoreFactory.java Wed Mar  2 17:30:05 2005
@@ -0,0 +1,7757 @@
+/*
+
+   Derby - Class org.apache.derbyTesting.unitTests.store.T_RawStoreFactory
+
+   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.*;
+
+// 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.monitor.Monitor;
+import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.iapi.services.uuid.UUIDFactory;
+import org.apache.derby.catalog.UUID;
+import org.apache.derby.iapi.services.property.PropertyUtil;
+import org.apache.derby.iapi.error.ExceptionSeverity;
+import org.apache.derby.iapi.error.StandardException;
+
+import org.apache.derby.iapi.store.access.*;
+import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo;
+
+import org.apache.derby.iapi.store.raw.xact.RawTransaction;
+import org.apache.derby.iapi.store.raw.data.RawContainerHandle;
+import org.apache.derby.iapi.store.raw.log.LogInstant;
+
+import org.apache.derby.iapi.types.DataValueDescriptor;
+
+// impl a logInstant implemented as log counter to test truncateLWMs
+import org.apache.derby.impl.store.raw.log.LogCounter;
+
+import org.apache.derby.iapi.types.SQLChar;
+
+import org.apache.derby.iapi.reference.Property;
+
+import org.apache.derby.iapi.services.io.FormatableBitSet;
+
+import java.io.*;
+import java.util.Properties;
+
+/**
+	A protocol unit test for the RawStore interface.
+*/
+
+public class T_RawStoreFactory extends T_MultiThreadedIterations {
+
+
+	static protected final String REC_001 = "McLaren";
+	static protected final String REC_002 = "Ferrari";
+	static protected final String REC_003 = "Benetton";
+	static protected final String REC_004 = "Prost";
+	static protected final String REC_005 = "Tyrell";
+	static protected final String REC_006 = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
+	static protected final String REC_007 = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
+	static protected final String REC_008 = "z";
+	static protected final String REC_009 = "nanonano";
+	static protected final String REC_010 = "fuzzbutt";
+	static protected final String REC_011 = "mork";
+	static protected final String REC_012 = "orson";
+	static protected final String REC_013 = "mindy";
+	static protected final String REC_014 = "thomas";
+	static protected final String REC_015 = "henry";
+	static protected final String REC_016 = "gordon";
+	static protected final String REC_017 = "mavis";
+	static protected final String REC_018 = "fatcontroller";
+	static protected final String REC_UNDO = "Lotus";
+	static protected final String REC_NULL = "NULL";
+
+	static final FormatableBitSet BS_COL_0 = new FormatableBitSet(1);
+
+	static protected final String SP1 = "savepoint1";
+	static protected final String SP2 = "savepoint2";
+
+	private static final String TEST_ROLLBACK_OFF = "derby.RawStore.RollbackTestOff";
+
+	private static boolean testRollbackProperty;// initialize in start
+	static protected boolean testRollback; // each thread has its own test rollback value
+
+	static protected RawStoreFactory	factory;
+	static protected LockFactory  lf;
+	static protected ContextService contextService;
+
+	static protected UUIDFactory uuidfactory;
+	protected  T_Util t_util;
+	protected int    openMode;	// mode flags used in all open containers.
+	protected boolean logDataForPurges = true; //used to test non-logged data purges
+
+	public T_RawStoreFactory() {
+		super();
+		BS_COL_0.set(0);
+	}
+
+	/**
+	  @exception StandardException cannot startup the context service
+	*/
+	public void boot(boolean create, Properties startParams)
+		 throws StandardException
+	{
+		super.boot(create, startParams);
+		contextService = ContextService.getFactory();
+	}
+
+	/*
+	** Methods required by T_Generic
+	*/
+
+	protected String getModuleToTestProtocolName() {
+		return RawStoreFactory.MODULE;
+	}
+
+	/**
+		Set up test
+
+		@exception T_Fail Unexpected behaviour from the API
+	 */
+	protected void setupTest() throws T_Fail {
+		
+		String rollbackOff = PropertyUtil.getSystemProperty(TEST_ROLLBACK_OFF);
+		testRollback = !Boolean.valueOf(rollbackOff).booleanValue();
+
+		testRollbackProperty = testRollback; // testRollbackProperty never changes
+
+		// 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 {
+
+			factory = (RawStoreFactory) Monitor.createPersistentService(getModuleToTestProtocolName(),
+								getTestService(), startParams);
+
+			if (factory == null) {
+				throw T_Fail.testFailMsg(getModuleToTestProtocolName() + " service not started.");
+			}
+
+			lf = factory.getLockFactory();
+			if (lf == null) {
+				throw T_Fail.testFailMsg("LockFactory.MODULE not found");
+			}
+
+			uuidfactory = Monitor.getMonitor().getUUIDFactory();
+
+		} catch (StandardException mse) {
+			throw T_Fail.exceptionFail(mse);
+		}
+
+		REPORT("testRollback=" + testRollback);
+
+		return;
+	}
+
+	protected String getTestService()
+	{
+		return "rawStoreTest";
+	}
+
+
+	/**
+	 * T_MultiThreadedIteration method
+	 *
+	 * @exception T_Fail Unexpected behaviour from the API
+	 */
+	protected void joinSetupTest() throws T_Fail {
+
+		T_Fail.T_ASSERT(factory != null, "raw store factory not setup ");
+		T_Fail.T_ASSERT(lf != null, "Lock factory not setup ");
+		T_Fail.T_ASSERT(contextService != null, "Context service not setup ");
+
+		testRollback = testRollbackProperty;
+
+	}
+
+	protected T_MultiThreadedIterations newTestObject() {
+		try
+		{
+			Class thisClass = this.getClass();
+			return (T_MultiThreadedIterations)(thisClass.newInstance());
+		}
+		catch (InstantiationException ie)
+		{
+			return new T_RawStoreFactory();
+		}	
+		catch (IllegalAccessException iae)
+		{
+			return new T_RawStoreFactory();
+		}
+	}	
+
+
+	/**
+	  run the test
+
+	  @exception T_Fail Unexpected behaviour from the API
+	*/
+	protected void runTestSet() throws T_Fail {
+
+		// get a utility helper
+		t_util = new T_Util(factory, lf, contextService);
+
+		ContextManager cm1 = contextService.newContextManager();
+		contextService.setCurrentContextManager(cm1);
+
+		try {
+
+
+			// Run the tests with data not logged for purges.
+			REPORT("Running tests with no data logged  for purges");
+			openMode = 0;		// logged by default
+			runPurgeWithNoDataLoggesTests();
+
+			// Run the tests in normal logged mode
+			REPORT("Running tests with logging requested");
+			openMode = 0;		// logged by default
+			runEachTest();
+
+			
+			// run the tests on temp tables
+			REPORT("Running tests for temp tables");
+			testRollback = false;	// obviously, we can't test rollback if we are not logging
+			runTempTests();
+
+			// Run the tests in unlogged mode
+			REPORT("Running tests in unlogged mode");
+			openMode = ContainerHandle.MODE_UNLOGGED | ContainerHandle.MODE_CREATE_UNLOGGED;
+			testRollback = false;	// obviously, we can't test rollback if we are not logging
+			runEachTest();
+
+			// if more runs are added here then you probably want to reset testRollback to
+			// its initial value, or add the runs before the unlogged mode.
+
+		} catch (StandardException se) {
+
+			cm1.cleanupOnError(se);
+			throw T_Fail.exceptionFail(se);
+		}
+		finally {
+			contextService.resetCurrentContextManager(cm1);
+		}
+	}
+
+	protected void runEachTest() throws T_Fail, StandardException {
+
+		t_util.setOpenMode(openMode);
+
+		// Transaction tests
+ 		T000();
+		T001();
+		T002();
+		T003();
+		T004();
+		T005();
+		T006();
+		T007();
+		T008();
+		T009();
+		T010();
+		T011();
+        T012();
+
+		// ContainerHandle tests
+		C010(0);
+		C011();
+		C012(1);
+		C014();
+		C200();
+		C201(0);
+		C201(1);
+
+		// Page tests
+		P001(0);
+		P002(0);
+		P003(0);
+		P004(0);
+		P005(0);
+		P006();
+		P007(0);
+		P008(0);
+		P009(0);
+		P011(0);
+		P012(0);
+		P013();
+		P014();
+		P015();
+		P016();
+		P017();
+		P018();
+		P019();		// test addPage with preallocation turned on
+		P020();		// test createContainer with initialPage set to 10 pages
+		P021();		// test preAllocate
+		P022();
+		P023(0);	// overflowThreshold test
+
+		// long row tests
+		P030(0);
+		P031(0);
+		P032(0);
+		P033(0);
+		P034(0);
+
+		P035(0);	// long column test
+
+
+
+		//run  the following test because they do lot of checks 
+		//on rollbacking when contyainer is unlogged nothing is rolled back
+		if((openMode & ContainerHandle.MODE_UNLOGGED) ==  ContainerHandle.MODE_UNLOGGED)
+		{
+			openMode = 0; //run them as logged for time being
+			t_util.setOpenMode(openMode);
+		}
+
+ 		// reclaiming space from long column and long rows - temp container
+		// row space is not reclaimed.
+		P036();
+		P037();
+		P038();
+		P039();
+		P040();
+		P041();
+		P042();
+		P043();
+
+
+		P050(); // rollback tests
+		P051();
+		P052();
+		P053();
+		P054();
+        P055(0);
+        P056(0);
+
+
+		P061(); // sparse row test
+
+        P071(); // serializable column test
+
+		// update/update partial tests with long rows
+		P701(0);
+        P702(0);
+		P703(0);
+		P704(0);
+		P705(0);
+
+		P706(0, false);
+		P706(0, true);
+		P707(0);
+		P708(0, false);
+		P708(0, true);
+
+
+		L001();	// large log record test
+
+		// checkpoint test
+		CP001();
+	}
+
+	protected void runTempTests() throws T_Fail, StandardException {
+
+		REPORT("Thread " + threadNumber + " entering temp tests ");
+
+		openMode = 0;			// logged by default
+		t_util.setOpenMode(openMode);	// logged mode should be overriden for temp tables
+
+		// now tests for temporary tables
+
+		C010(ContainerHandle.TEMPORARY_SEGMENT);
+		C012(ContainerHandle.TEMPORARY_SEGMENT);
+		//P001(ContainerHandle.TEMPORARY_SEGMENT);
+		//P002(ContainerHandle.TEMPORARY_SEGMENT);
+		P003(ContainerHandle.TEMPORARY_SEGMENT);
+		P004(ContainerHandle.TEMPORARY_SEGMENT);
+		P005(ContainerHandle.TEMPORARY_SEGMENT);
+		P011(ContainerHandle.TEMPORARY_SEGMENT);
+		P012(ContainerHandle.TEMPORARY_SEGMENT);
+		P030(ContainerHandle.TEMPORARY_SEGMENT);
+
+		// update/update partial tests with long rows
+		P055(ContainerHandle.TEMPORARY_SEGMENT);
+		P056(ContainerHandle.TEMPORARY_SEGMENT);
+
+		P701(ContainerHandle.TEMPORARY_SEGMENT);
+		P702(ContainerHandle.TEMPORARY_SEGMENT);
+		P703(ContainerHandle.TEMPORARY_SEGMENT);
+		P704(ContainerHandle.TEMPORARY_SEGMENT);
+		P705(ContainerHandle.TEMPORARY_SEGMENT);
+		P706(ContainerHandle.TEMPORARY_SEGMENT, false);
+		P706(ContainerHandle.TEMPORARY_SEGMENT, true);
+		P707(ContainerHandle.TEMPORARY_SEGMENT);
+
+		// tests specific to temp tables
+
+		// checking truncate at commit/rollback works
+		TC001();
+		TC002(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, true);
+		TC002(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, false);
+		TC002(0, false);
+
+		// checking an explict drop works ...
+		TC003(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, true);
+		TC003(ContainerHandle.MODE_TRUNCATE_ON_COMMIT, false);
+		TC003(0, false);
+		TC003(0, true);
+		TC003(ContainerHandle.MODE_DROP_ON_COMMIT, true);
+		TC003(ContainerHandle.MODE_DROP_ON_COMMIT, false);
+
+		// various combinations of opens ...
+		TC004all();
+
+		REPORT("Thread " + threadNumber + " exiting temp tests ");
+ 	}
+
+
+	protected void runPurgeWithNoDataLoggesTests() throws T_Fail, StandardException {
+
+		REPORT("Thread " + threadNumber + " entering purges with no data logged tests ");
+		logDataForPurges = false;
+		P005(0);
+		P006();
+		P014();
+		P036();
+		P037();
+		P709();
+		P710();
+		P711();
+		REPORT("Thread " + threadNumber + " exiting purge with no data logged tests ");
+		logDataForPurges = true;
+	}
+	/*
+	** The tests
+	**		Tnnn indicates a test that is mainly testing the Transaction interface
+	**		Cnnn indicates a test that is mainly testing the ContainerHandle interface
+	**		Pnnn indicates a test that is mainly testing the Page interface
+	**
+	**	nnn < 200 tends to indicate purely API tests, ie checking methods
+	**		are callable and return the right value. This includes negative tests.
+	**
+	**  nnn >= 200 tends to indicate more involved tests, ie ones that test the
+	**			methods actually did something.
+
+	*/
+
+	/**
+		T000 - ensure a transaction starts out idle.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void T000() throws T_Fail, StandardException {
+
+		Transaction t1 = t_util.t_startTransaction();
+
+		t1.close();
+
+
+		t1 = t_util.t_startInternalTransaction();
+
+		t1.close();
+
+		t1 = t_util.t_startTransaction();
+		Transaction ti = t_util.t_startInternalTransaction();
+
+		ti.close();
+
+		t1.close();
+
+		PASS("T000");
+	}
+
+	/**
+		T001 - start and commit an empty transaction.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void T001() throws T_Fail, StandardException {
+
+		Transaction t1 = t_util.t_startTransaction();
+
+		t_util.t_commit(t1);
+
+		t1.close();
+
+		PASS("T001");
+	}
+
+	/**
+		T002 - start and abort an empty transaction.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void T002() throws T_Fail, StandardException {
+
+		Transaction t1 = t_util.t_startTransaction();
+
+		t_util.t_abort(t1);
+
+		t1.close();
+
+		PASS("T002");
+	}
+
+	/**
+		T003 - start and commit an empty transaction and then ensure
+		that the transaction remains open for another commit.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void T003() throws T_Fail, StandardException {
+
+		Transaction t1 = t_util.t_startTransaction();
+
+		t_util.t_commit(t1);
+
+		t_util.t_commit(t1);
+		t_util.t_abort(t1);
+
+		t1.close();
+
+		PASS("T003");
+	}
+
+	/**
+		T004 - start and abort an empty transaction and then ensure
+		that the transaction remains open for a commit and another abort.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void T004() throws T_Fail, StandardException {
+
+		Transaction t1 = t_util.t_startTransaction();
+
+		t_util.t_abort(t1);
+
+		t_util.t_commit(t1);
+
+		t_util.t_abort(t1);
+
+		t1.close();
+
+		PASS("T004");
+	}
+
+
+	/**
+		T005 check transaction identifiers on idle transactions.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+
+	*/
+	protected void T005() throws T_Fail, StandardException {
+
+		Transaction t1 = t_util.t_startTransaction();
+
+        // local transactions do not have global id's
+		GlobalTransactionId id1 = t1.getGlobalId();
+		if (id1 != null)
+			throw T_Fail.testFailMsg("null not returned from local Transaction.getId()");
+        t1.close();
+
+        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};
+
+        t1 = t_util.t_startGlobalTransaction(42, global_id, branch_id);
+
+        id1 = t1.getGlobalId();
+
+		if (!id1.equals(id1))
+			throw T_Fail.testFailMsg("TransactionId does not compare equal to itself");
+
+		if (!id1.equals(t1.getGlobalId()))
+			throw T_Fail.testFailMsg("TransactionId has changed without any activity on Transaction");
+
+		if (id1.equals(this))
+			throw T_Fail.testFailMsg("TransactionId compared equal to an non-transaction id object");
+
+		t1.close();
+		t1 = null;
+
+        // change the branch_id for the second global xact.
+        branch_id[63] = 82;
+		Transaction t2 = 
+            t_util.t_startGlobalTransaction(42, global_id, branch_id);
+
+		GlobalTransactionId id2 = t2.getGlobalId();
+		if (id2 == null)
+			throw T_Fail.testFailMsg("null returned from Transaction.getId()");
+
+		if (id1.equals(id2))
+			throw T_Fail.testFailMsg("TransactionId's returned equal from different transactions");
+		if (id2.equals(id1))
+			throw T_Fail.testFailMsg("TransactionId's returned equal from different transactions");
+
+		t2.close();
+
+		PASS("T005");
+	}
+
+	/**
+		T006 - savepoint basic API testing
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void T006() throws T_Fail, StandardException {	
+
+		Transaction t1 = t_util.t_startTransaction();
+
+		// check a random savepoint name is not accepted
+		t_util.t_checkInvalidSavePoint(t1, "sdfjsdfg");
+
+
+		t1.setSavePoint(SP1, null);
+
+		t1.rollbackToSavePoint(SP1, null);	// leaves savepoint around
+		t1.rollbackToSavePoint(SP1, null);	// therefore this should work
+
+		t1.releaseSavePoint(SP1, null);
+
+		// SP1 should no longer exist
+		t_util.t_checkInvalidSavePoint(t1, SP1);
+
+		// should be able to re-use it ...
+		t1.setSavePoint(SP1, null);
+		t1.rollbackToSavePoint(SP1, null);	// leaves savepoint around
+		t1.rollbackToSavePoint(SP1, null);	// therefore this should work
+
+		t1.releaseSavePoint(SP1, null);
+		t_util.t_checkInvalidSavePoint(t1, SP1);
+
+		t_util.t_commit(t1);
+		t1.close();
+
+		PASS("T006");
+	}
+
+
+	/**
+		T007 - savepoint nesting testing
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void T007() throws T_Fail, StandardException {	
+
+		Transaction t1 = t_util.t_startTransaction();
+		int position = 0;
+
+		/*
+		** Push two save points and release the first, both should disappear
+		*/
+		t1.setSavePoint(SP1, null);
+		t1.setSavePoint(SP2, null);
+
+		position = t1.releaseSavePoint(SP1, null);
+		if (position  != 0)
+			throw T_Fail.testFailMsg("Save Point Position in the stack isincorrect:"+
+									 position);
+
+
+		// SP1 and SP2 should no longer exist
+		t_util.t_checkInvalidSavePoint(t1, SP1);
+		t_util.t_checkInvalidSavePoint(t1, SP2);
+
+		/*
+		** Push two save points and remove the second, first should remain
+		*/
+		t1.setSavePoint(SP1, null);
+		t1.setSavePoint(SP2, null);
+
+		t1.rollbackToSavePoint(SP2, null);	// leaves savepoint around
+		position = t1.rollbackToSavePoint(SP2, null);	// therefore this should work
+		
+		if (position  != 2)
+			throw T_Fail.testFailMsg("Save Point Position in the stack isincorrect:"+
+									 position);
+
+
+
+		position = t1.releaseSavePoint(SP2, null);
+		if (position  != 1)
+			throw T_Fail.testFailMsg("Save Point Position in the stack is incorrect:"+
+									 position);
+
+
+		t_util.t_checkInvalidSavePoint(t1, SP2);
+
+		t1.rollbackToSavePoint(SP1, null);	// this is the main test
+
+		t1.releaseSavePoint(SP1, null);
+		t_util.t_checkInvalidSavePoint(t1, SP1);
+
+		/*
+		** Push two save points and rollback to the first, the second should disappear
+		*/
+		t1.setSavePoint(SP1, null);
+		t1.setSavePoint(SP2, null);
+
+		position = t1.rollbackToSavePoint(SP1, null);	// leaves SP1, removes SP2
+		if (position  != 1)
+			throw T_Fail.testFailMsg("Save Point Position in the stack is incorrect:"+
+												 position);
+
+		
+		t_util.t_checkInvalidSavePoint(t1, SP2);
+		t1.rollbackToSavePoint(SP1, null);
+
+		t1.releaseSavePoint(SP1, null);
+
+		t_util.t_commit(t1);
+		t1.close();
+
+		PASS("T007");
+	}
+
+	/**
+		T008 - savepoint  testing, ensure save points disappear at commit or abort.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void T008() throws T_Fail, StandardException {	
+
+		Transaction t1 = t_util.t_startTransaction();
+		int position1 = 0;
+		int position2 = 0;
+
+		position1 = t1.setSavePoint(SP1, null);
+		position2 = t1.setSavePoint(SP2, null);
+
+		if (position1 != 1 && position2 != 2)
+			throw T_Fail.testFailMsg("Save Point Position in the Stack seeme to wrong");
+
+		t1.commit();
+
+		t_util.t_checkInvalidSavePoint(t1, SP1);
+		t_util.t_checkInvalidSavePoint(t1, SP2);
+
+		position1 = t1.setSavePoint(SP1, null);
+		position2 = t1.setSavePoint(SP2, null);
+		
+		if (position1 != 1 && position2 != 2)
+			throw T_Fail.testFailMsg("Save Point Position in the Stack seeme to wrong");
+
+		t1.abort();
+		position1 = t1.setSavePoint(SP1, null);
+		position2 = t1.setSavePoint(SP2, null);
+		if (position1 != 1 && position2 != 2)
+			throw T_Fail.testFailMsg("Save Point Position in the Stack seeme to wrong");
+		t1.abort();
+		t_util.t_checkInvalidSavePoint(t1, SP1);
+		t_util.t_checkInvalidSavePoint(t1, SP2);
+
+		t1.close();
+
+		PASS("T008");
+	}
+
+
+	/**
+		T009 - add a container and remove it within the same transaction.
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+
+	*/
+
+	protected void T009() throws StandardException, T_Fail {
+		Transaction t = t_util.t_startTransaction();
+
+		long cid = t_util.t_addContainer(t, 0, 4096);
+		t_util.t_dropContainer(t, 0, cid);
+
+		ContainerKey id = new ContainerKey(0, cid);
+		ContainerHandle ch = t.openContainer(id, ContainerHandle.MODE_READONLY);
+		if (ch != null)
+			throw T_Fail.testFailMsg("Dropped Container should not open");
+
+		t_util.t_commit(t);
+
+		t.close();
+
+		PASS("T009");
+	}
+
+	/**
+		T010 - add a container with a default size and remove it within the same transaction.
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+
+	*/
+
+	protected void T010() throws StandardException, T_Fail {
+		Transaction t1 = t_util.t_startTransaction();
+
+		long cid = t_util.t_addContainer(t1, 0);
+
+		t_util.t_dropContainer(t1, 0, cid);
+
+		ContainerKey id = new ContainerKey(0, cid);
+		ContainerHandle ch = t1.openContainer(id, ContainerHandle.MODE_READONLY);
+		if (ch != null)
+			throw T_Fail.testFailMsg("Dropped Container should not open");
+
+		t_util.t_commit(t1);
+
+		t1.close();
+
+		PASS("T010");
+	}
+
+	/**
+		T011 - see that a container remains open over the commit of an open transaction..
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+
+	*/
+
+	protected void T011() throws StandardException, T_Fail {
+
+		Transaction t = t_util.t_startInternalTransaction();
+
+
+		long cid = t_util.t_addContainer(t, 0);
+
+		ContainerHandle c;
+
+		c = t_util.t_openContainer(t, 0, cid, true);
+
+		t.commit();
+
+		// container should still be open
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		t.commit();
+
+		// page should still be latched
+		if (!page.isLatched())
+			throw T_Fail.testFailMsg("page not latched after commit of internal transaction");
+
+		page.unlatch();
+		c.close();
+
+		t.commit();
+
+		c = t_util.t_openContainer(t, 0, cid, true);
+		page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		// container and page should be closed
+		t.abort();
+		if (page.isLatched())
+			throw T_Fail.testFailMsg("page latched after abort of internal transaction");
+
+		try {
+			page = t_util.t_getLastPage(c);
+			throw T_Fail.testFailMsg("container open after abort of internal transaction");
+
+		} catch (StandardException te) {
+		}
+
+		t_util.t_dropContainer(t, 0, cid);	// cleanup
+
+		t_util.t_commit(t);
+
+		t.close();
+
+		PASS("T011");	
+	}
+
+	/**
+		Test Xact.makeRecordHandle()
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void T012() throws StandardException, T_Fail {
+
+		Transaction t = t_util.t_startTransaction();		
+
+		long cid = t_util.t_addContainer(t, 0);
+
+		ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		RecordHandle r1, r2;
+		RecordHandle new_r1, new_r2;
+
+		T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
+		T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
+
+		r1 = t_util.t_insertAtSlot(page, 0, row1);
+        new_r1 = c.makeRecordHandle(r1.getPageNumber(), r1.getId());
+
+		t_util.t_checkFetch(page, new_r1, REC_001);
+
+		r2 = t_util.t_insertAtSlot(page, 1, row2);
+
+		if (r2 != null)
+        {
+            new_r2 = 
+                c.makeRecordHandle(r2.getPageNumber(), r2.getId());
+			t_util.t_checkFetch(page, r2, REC_002);
+        }
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("T012");
+
+	}
+
+	/**
+		C010 - Create a container within a transaction, commit and the re-open
+		the container twice.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+
+	*/
+	protected void C010(int segment) throws T_Fail, StandardException {
+
+		Transaction t = t_util.t_startTransaction();
+
+		long cid = t_util.t_addContainer(t, segment);
+
+		t_util.t_commit(t);
+	
+		ContainerHandle c1, c2;
+
+		c1 = t_util.t_openContainer(t, segment, cid, true);
+		c1 = t_util.t_openContainer(t, segment, cid, true);
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("C010");
+
+	}
+
+	/**
+		C011 - Create a container withina transaction, commit and the re-open
+		the container in update and non-update mode.
+		
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+
+	*/
+	protected void C011() throws T_Fail, StandardException {
+
+		Transaction t = t_util.t_startTransaction();
+
+		long cid = t_util.t_addContainer(t, 0);
+
+		t_util.t_commit(t);
+	
+		ContainerHandle c1, c2;
+
+		c1 = t_util.t_openContainer(t, 0, cid, false);
+		c1 = t_util.t_openContainer(t, 0, cid, true);
+
+		t_util.t_dropContainer(t, 0, cid);	// cleanup
+
+		t_util.t_commit(t);
+		t.close();
+		PASS("C011");
+
+	}
+
+	/**
+		C012 - Drop a container within a transaction, commit, see that it is deleted.
+		Drop a container within a transaction, rollback and re-open and see
+		that it is not deleted. 
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Standard Derby error policy
+	*/
+	protected void C012(long segment) throws T_Fail, StandardException {
+
+		Transaction t = t_util.t_startTransaction();
+
+		long cid = t_util.t_addContainer(t, segment);
+		t_util.t_commit(t);
+
+		ContainerHandle c1 = t_util.t_openContainer(t, segment, cid, true);
+
+		t_util.t_dropContainer(t, segment, cid);
+
+		if (testRollback)
+		{
+			t_util.t_abort(t);			// this should rollback the drop
+			c1 = t_util.t_openContainer(t, segment, cid, true);
+
+			REPORT("rollback of drop container tested");
+
+			t_util.t_dropContainer(t, segment, cid);
+		}
+
+		t_util.t_commit(t);
+
+		ContainerKey id = new ContainerKey(segment, cid);
+		c1 = t.openContainer(id, (ContainerHandle.MODE_FORUPDATE | openMode));	// this should fail
+		if (c1 != null)
+			throw T_Fail.testFailMsg("Deleted Container should fail to open");
+
+		t_util.t_commit(t);
+		t.close();
+		PASS("C012");
+	}
+
+	/**
+		C014 - Open a container for locking only.
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Standard Derby error policy
+	*/
+	protected void C014() throws T_Fail, StandardException {
+
+		Transaction t = t_util.t_startTransaction();
+
+		ContainerKey id = new ContainerKey(77, 45);
+		ContainerHandle c = t.openContainer(id,
+			ContainerHandle.MODE_OPEN_FOR_LOCK_ONLY);
+
+		if (c == null)
+			throw T_Fail.testFailMsg("open of a container for lock only failed.");
+
+		RecordHandle rh1 = c.makeRecordHandle(23, 456);
+		if (rh1 == null)
+			throw T_Fail.testFailMsg("makeRecordHandle returned null");
+		c.getLockingPolicy().lockRecordForRead(t, c, rh1, true, true);
+
+
+		RecordHandle rh2 = c.makeRecordHandle(23, 7);
+		if (rh2 == null)
+			throw T_Fail.testFailMsg("makeRecordHandle returned null");
+		c.getLockingPolicy().lockRecordForRead(t, c, rh2, true, false);
+
+		RecordHandle rh3 = c.makeRecordHandle(23, 9);
+		c.getLockingPolicy().lockRecordForWrite(t, rh3, false, true);
+		if (rh3 == null)
+			throw T_Fail.testFailMsg("makeRecordHandle returned null");
+
+		c.getLockingPolicy().unlockRecordAfterRead(t, c, rh2, false, true);
+
+		c.close();
+
+		t.commit();
+
+		t.close();
+
+		PASS("C014");
+	}
+
+	/**
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void C200() throws T_Fail, StandardException {
+
+		Transaction t1 = t_util.t_startTransaction();
+
+		long cid = t_util.t_addContainer(t1, 0);
+
+		t_util.t_commit(t1);
+
+		ContainerHandle c1;
+		Page lastPage;
+		RecordHandle rh001, rh002, rh003;
+		T_RawStoreRow row;
+	
+		REPORT("see if the container can be opened again");
+		c1 = t_util.t_openContainer(t1, 0, cid, false);
+
+		c1.close();
+		t_util.t_commit(t1);
+
+		REPORT("insert a record into the container.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, true);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Could get container's last page");
+
+		if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
+			throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
+
+		row = new T_RawStoreRow(REC_001);
+		if (!lastPage.spaceForInsert())
+			throw T_Fail.testFailMsg("No room for record on page");
+
+		rh001 = t_util.t_insert(lastPage, row);
+		if (rh001 == null)
+			throw T_Fail.testFailMsg("Failed to insert record");
+
+		// see if we can fetch that record
+		t_util.t_checkFetch(lastPage, rh001, REC_001);
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+		c1 = null;
+
+
+		REPORT("read record just inserted.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, false);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Could get container's last page");
+
+		t_util.t_checkFetch(lastPage, rh001, REC_001);
+		t_util.t_checkFetchFirst(lastPage, REC_001);
+		t_util.t_checkFetchLast(lastPage, REC_001);
+
+		t_util.t_commit(t1);
+		lastPage = null;
+		c1 = null;
+
+
+		REPORT("insert 2 more records.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, true);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Could get container's last page");
+
+		if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
+			throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
+
+		row = new T_RawStoreRow(REC_002);
+		if (!lastPage.spaceForInsert())
+			throw T_Fail.testFailMsg("No room for record on page");
+
+		if (!lastPage.recordExists(rh001, false))
+			throw T_Fail.testFailMsg("Record 001 has vanished");
+
+		//
+
+		// RESOLVE: just insert them for now, order is 002,001,003
+		// 001 is already on the page
+
+		rh002 = t_util.t_insertAtSlot(lastPage, 0, row);
+		row = new T_RawStoreRow(REC_003);
+		rh003 = t_util.t_insert(lastPage, row);
+		// Order is 002, 001, 003
+	
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+		c1 = null;
+	
+		REPORT("checks on all 3 records.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, false);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Could get container's last page");
+
+		// Order is 002, 001, 003
+		t_util.t_checkFetch(lastPage, rh001, REC_001);
+		t_util.t_checkFetch(lastPage, rh002, REC_002);
+		t_util.t_checkFetch(lastPage, rh003, REC_003);
+
+
+		t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh001.getId()), REC_001);
+		t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh002.getId()), REC_002);
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+
+		REPORT("start deleting.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, true);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Could get container's last page");
+
+		// Order is 002, 001, 003
+		t_util.t_checkFetch(lastPage, rh001, REC_001);
+		t_util.t_checkFetch(lastPage, rh002, REC_002);
+		t_util.t_checkFetch(lastPage, rh003, REC_003);
+
+		lastPage.delete(rh001, (LogicalUndo)null);
+		if (lastPage.fetch(
+              rh001, new DataValueDescriptor[0], (FormatableBitSet) null, false) != null)
+        {
+			throw T_Fail.testFailMsg("deleted record is still present");
+        }
+		// Order is 002,  003
+		t_util.t_checkFetch(lastPage, rh002, REC_002);
+		t_util.t_checkFetch(lastPage, rh003, REC_003);
+
+		t_util.t_checkFetchNext(lastPage, rh002, REC_003);
+		t_util.t_checkFetchPrevious(lastPage, rh003, REC_002);
+
+		lastPage.delete(rh002, (LogicalUndo)null);
+		if (lastPage.fetch(
+              rh002, new DataValueDescriptor[0], (FormatableBitSet) null, false) != null)
+        {
+			throw T_Fail.testFailMsg("deleted record is still present");
+        }
+
+		t_util.t_checkFetch(lastPage, rh003, REC_003);
+		t_util.t_checkFetchFirst(lastPage, REC_003);
+		t_util.t_checkFetchLast(lastPage, REC_003);
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+
+		REPORT("update the remaining record.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, true);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Could get container's last page");
+
+		// Order is 003
+		t_util.t_checkFetch(lastPage, rh003, REC_003);
+
+		T_RawStoreRow urow = new T_RawStoreRow(REC_004);
+
+		if (lastPage.fetch(
+              rh003, new DataValueDescriptor[0], (FormatableBitSet) null, true) == null)
+        {
+			throw T_Fail.testFailMsg("fetch for update returned false");
+        }
+	
+		if (!lastPage.update(rh003, urow.getRow(), (FormatableBitSet) null))
+			throw T_Fail.testFailMsg("update returned false");
+
+		// Order is 003
+		t_util.t_checkFetch(lastPage, rh003, REC_004);
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+
+		t_util.t_dropContainer(t1, 0, cid); // cleanup
+
+		t_util.t_commit(t1);
+		t1.close();
+		   
+		PASS("C200");
+
+	}
+
+	/**
+		C201 - Create container with different page size, minimum record size,
+		inserting into these containers to check if the variables are set correctly.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void C201(int whatPage) throws T_Fail, StandardException {
+
+		int pageSize = (whatPage == 0 ? 4096 : 32768);
+
+		Transaction t1 = t_util.t_startTransaction();
+
+		REPORT("create container with pageSize " + pageSize + ", spareSpace " + 0 + ", minimumRecordSize " + pageSize/2);
+		long cid = t_util.t_addContainer(t1, 0, pageSize, 0, pageSize/2, false);
+		
+		t_util.t_commit(t1);
+
+		ContainerHandle c1;
+		Page lastPage;
+		RecordHandle rh001, rh002, rh003;
+		T_RawStoreRow row;
+	
+		REPORT("see if the container can be opened again");
+		c1 = t_util.t_openContainer(t1, 0, cid, false);
+
+		c1.close();
+		t_util.t_commit(t1);
+
+		REPORT("insert a record into the container.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, true);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Couldn't get container's last page");
+
+		if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
+			throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
+
+		row = new T_RawStoreRow(REC_001);
+		if (!lastPage.spaceForInsert())
+			throw T_Fail.testFailMsg("No room for record on page");
+
+		rh001 = t_util.t_insert(lastPage, row);
+		if (rh001 == null)
+			throw T_Fail.testFailMsg("Failed to insert record");
+
+		// see if we can fetch that record
+		t_util.t_checkFetch(lastPage, rh001, REC_001);
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+		c1 = null;
+
+		REPORT("read record just inserted.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, false);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Couldn't get container's last page");
+
+		t_util.t_checkFetch(lastPage, rh001, REC_001);
+		t_util.t_checkFetchFirst(lastPage, REC_001);
+		t_util.t_checkFetchLast(lastPage, REC_001);
+
+		t_util.t_commit(t1);
+		lastPage = null;
+		c1 = null;
+
+		// negative testing
+		REPORT("try inserting 1 more record, but there should be no room on page for it.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, true);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Couldn't get container's last page");
+
+		if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
+			throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
+
+		row = new T_RawStoreRow(REC_002);
+		if (lastPage.spaceForInsert())
+        {
+			throw T_Fail.testFailMsg("Did not get no room for record on page error");
+        }
+
+		if (!lastPage.recordExists(rh001, false))
+			throw T_Fail.testFailMsg("Record 001 has vanished");
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+		c1 = null;
+
+		t_util.t_dropContainer(t1, 0, cid); // cleanup
+		t_util.t_commit(t1);
+		//t1.close();
+
+
+		//t1 = t_util.t_startTransaction();
+
+		REPORT("create container with pageSize " + pageSize + ", spareSpace " + 0 + ", minimumRecordSize " + pageSize);
+		REPORT("this should set minimumRecordSize to the default 100");
+		cid = t_util.t_addContainer(t1, 0, pageSize, 0, pageSize, false);
+		
+		t_util.t_commit(t1);
+
+		REPORT("see if the container can be opened again");
+		c1 = t_util.t_openContainer(t1, 0, cid, false);
+
+		c1.close();
+		t_util.t_commit(t1);
+
+		REPORT("insert a record into the container.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, true);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Couldn't get container's last page");
+
+		if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
+			throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
+
+		row = new T_RawStoreRow(REC_001);
+		if (!lastPage.spaceForInsert())
+			throw T_Fail.testFailMsg("No room for record on page");
+
+		rh001 = t_util.t_insert(lastPage, row);
+		if (rh001 == null)
+			throw T_Fail.testFailMsg("Failed to insert record");
+
+		// see if we can fetch that record
+		t_util.t_checkFetch(lastPage, rh001, REC_001);
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+		c1 = null;
+
+		REPORT("read record just inserted.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, false);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Couldn't get container's last page");
+
+		t_util.t_checkFetch(lastPage, rh001, REC_001);
+		t_util.t_checkFetchFirst(lastPage, REC_001);
+		t_util.t_checkFetchLast(lastPage, REC_001);
+
+		t_util.t_commit(t1);
+		lastPage = null;
+		c1 = null;
+
+		REPORT("insert 2 more records.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, true);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Could get container's last page");
+
+		if (lastPage.getPageNumber() != ContainerHandle.FIRST_PAGE_NUMBER)
+			throw T_Fail.testFailMsg("Initial page must be " + ContainerHandle.FIRST_PAGE_NUMBER + ", is " + lastPage.getPageNumber());
+
+		row = new T_RawStoreRow(REC_002);
+		if (!lastPage.spaceForInsert())
+			throw T_Fail.testFailMsg("No room for record on page");
+
+		if (!lastPage.recordExists(rh001, false))
+			throw T_Fail.testFailMsg("Record 001 has vanished");
+
+		rh002 = t_util.t_insertAtSlot(lastPage, 0, row);
+		row = new T_RawStoreRow(REC_003);
+		rh003 = t_util.t_insert(lastPage, row);
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+		c1 = null;
+	
+		REPORT("checks on all 3 records.");
+
+		c1 = t_util.t_openContainer(t1, 0, cid, false);
+
+		lastPage = t_util.t_getLastPage(c1);
+		if (lastPage == null)
+			throw T_Fail.testFailMsg("Could get container's last page");
+
+		// Order is 002, 001, 003
+		t_util.t_checkFetch(lastPage, rh001, REC_001);
+		t_util.t_checkFetch(lastPage, rh002, REC_002);
+		t_util.t_checkFetch(lastPage, rh003, REC_003);
+
+
+		t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh001.getId()), REC_001);
+		t_util.t_checkFetch(lastPage, lastPage.getRecordHandle(rh002.getId()), REC_002);
+
+		lastPage.unlatch();
+		lastPage = null;
+
+		t_util.t_commit(t1);
+
+		c1 = null;
+
+		// clean ip
+		t_util.t_dropContainer(t1, 0, cid);
+		t_util.t_commit(t1);
+		t1.close();
+
+		PASS("C201 - " + whatPage);
+
+	}
+
+	/**
+		Page tests
+	 */
+	 /**
+	    Create a container, ensure it has one page with no records. Then test
+		all the things we can do with an empty page opened read-only in the container.
+		Then add a new page, ensure it has the correct page number and is empty.
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void P001(long segment) throws T_Fail, StandardException {
+
+		Transaction t = t_util.t_startTransaction();
+
+		long cid = t_util.t_addContainer(t, segment);
+
+		t_util.t_commit(t);
+
+		// Get the first page & check the record counts are zero
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, false);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		t_util.t_checkEmptyPage(page);
+
+		if (Page.FIRST_SLOT_NUMBER != 0)
+			throw T_Fail.testFailMsg("Page.FIRST_SLOT_NUMBER must be 0, is " + Page.FIRST_SLOT_NUMBER);
+
+		page.unlatch();
+		page = null;
+
+		// get the last page and check it is the first page
+		page = t_util.t_getLastPage(c);
+
+		t_util.t_checkPageNumber(page, ContainerHandle.FIRST_PAGE_NUMBER);
+	
+		t_util.t_checkEmptyPage(page);
+
+		t_util.t_commit(t);
+
+		// t_util.t_addPage checks that the page is empty.
+		c = t_util.t_openContainer(t, segment, cid, true);
+		page = t_util.t_addPage(c);
+
+		t_util.t_checkPageNumber(page, ContainerHandle.FIRST_PAGE_NUMBER + 1);
+		page.unlatch();
+
+		page = t_util.t_addPage(c);
+		t_util.t_checkPageNumber(page, ContainerHandle.FIRST_PAGE_NUMBER + 2);
+		page.unlatch();
+
+		t_util.t_commit(t);
+
+		c = t_util.t_openContainer(t, segment, cid, true);
+		page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+		t_util.t_updateSlotOutOfRange(page, 0);
+		t_util.t_updateSlotOutOfRange(page, -1);
+		t_util.t_updateSlotOutOfRange(page, 1);
+
+
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+		t_util.t_commit(t);
+
+		// RESOLVE drop container
+
+		t.close();
+
+		PASS("P001");
+	}
+
+	/**
+		Insert rows on the first page until the page is full, then add a page
+		and repeat the test (for a total of three pages with full rows).
+		Fetch the rows back by handle and slot methods.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void P002(long segment) throws StandardException, T_Fail {
+
+		Transaction t = t_util.t_startTransaction();		
+
+		long cid = t_util.t_addContainer(t, segment);
+
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+		t_util.t_checkEmptyPage(page);
+
+		RecordHandle rh;
+		T_RawStoreRow row;
+		int	recordCount[] = {0,0,0};
+
+		for (int i = 0; i < 3;) {
+			row = new T_RawStoreRow(REC_001 + i + "X" + recordCount[i]);
+
+			boolean spaceThere = page.spaceForInsert();
+
+			rh = t_util.t_insert(page, row);
+
+			if (rh != null) {
+				recordCount[i]++;
+				if (!spaceThere)
+					REPORT("record inserted after spaceForInsert() returned false, count is " + recordCount[i]);
+			} else {
+				if (spaceThere)
+					REPORT("record insert failed after spaceForInsert() returned true, count is " + recordCount[i]);
+			}
+
+			t_util.t_checkRecordCount(page, recordCount[i], recordCount[i]);
+
+			if (rh != null)
+				continue;
+
+			page.unlatch();
+			page = null;
+
+			if (++i < 3) {
+				page = t_util.t_addPage(c);
+				t_util.t_checkEmptyPage(page);
+			}
+		}
+		t_util.t_commit(t);
+
+		for (int i = 0; i < 3; i++) {
+			REPORT("RecordCount on page " + i + "=" + recordCount[i]);
+		}
+
+		// now check that we read the same number of records back
+		// using the handle interface
+		c = t_util.t_openContainer(t, segment, cid, false);
+
+		long pageNumber = ContainerHandle.FIRST_PAGE_NUMBER;
+		for (int i = 0; i < 3; i++, pageNumber++) {
+			page = t_util.t_getPage(c, pageNumber);
+			t_util.t_checkRecordCount(page, recordCount[i], recordCount[i]);
+			rh = t_util.t_checkFetchFirst(page, REC_001 + i + "X" + 0);
+			for (int j = 1; j < recordCount[i]; j++)
+				rh = t_util.t_checkFetchNext(page, rh, REC_001 + i + "X" + j);
+
+            try
+            {
+                rh = page.fetchFromSlot(
+                        null, 
+                        page.getSlotNumber(rh) + 1, 
+                        new DataValueDescriptor[0], 
+                        (FetchDescriptor) null, 
+                        false);
+
+				throw T_Fail.testFailMsg(
+                        "reading more rows on page than were written");
+            }
+            catch (StandardException se)
+            {
+                // expected error.
+            }
+
+			rh = t_util.t_checkFetchLast(page, REC_001 + i + "X" + (recordCount[i] - 1));
+			for (int j = recordCount[i] - 2; j >= 0; j--)
+				rh = t_util.t_checkFetchPrevious(page, rh, REC_001 + i + "X" + j);
+
+			page.unlatch();
+			page = null;
+		}
+		t_util.t_commit(t);
+
+		// now check that we read the same number of records back
+		// using the slot interface
+		c = t_util.t_openContainer(t, segment, cid, false);
+
+		pageNumber = ContainerHandle.FIRST_PAGE_NUMBER;
+		for (int i = 0; i < 3; i++, pageNumber++) {
+			page = t_util.t_getPage(c, pageNumber);
+		
+			for (int j = 0; j < recordCount[i]; j++)
+				t_util.t_checkFetchBySlot(page, j, REC_001 + i + "X" + j,
+										false, false);
+
+			t_util.t_readOnlySlotOutOfRange(page, recordCount[i]);
+
+			page.unlatch();
+			page = null;
+		}
+
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+
+		t_util.t_commit(t);
+
+		t.close();
+
+		PASS("P002");
+	}
+
+	/**
+		Test Page.delete
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#delete
+	*/
+
+	protected void P003(long segment) throws StandardException, T_Fail {
+
+		Transaction t = t_util.t_startTransaction();		
+
+		long cid = t_util.t_addContainer(t, segment);
+
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		RecordHandle r1, r2;
+
+		T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
+		T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
+
+		r1 = t_util.t_insertAtSlot(page, 0, row1);
+		r2 = t_util.t_insertAtSlot(page, 1, row2);
+
+		t_util.t_checkFetch(page, r1, REC_001);
+		if (r2 != null)
+			t_util.t_checkFetch(page, r2, REC_002);
+
+		t_util.t_checkRecordCount(page, 2, r2 == null ? 1 : 2);
+
+		// delete the first
+		if (!page.delete(r1, (LogicalUndo)null))
+			throw T_Fail.testFailMsg("delete() returned false");
+
+		t_util.t_checkRecordCount(page, 2, r2 == null ? 0 : 1);
+
+		if (page.delete(r1, (LogicalUndo)null))
+			throw T_Fail.testFailMsg("delete() returned true on already deleted record");
+
+		t_util.t_checkRecordCount(page, 2, r2 == null ? 0 : 1);
+
+		if (page.recordExists(r1, false))
+			throw T_Fail.testFailMsg("recordExists() returned true for deleted record");
+
+		// check the other record is still there
+		if (r2 != null)
+			t_util.t_checkFetch(page, r2, REC_002);
+
+
+		if (!page.isDeletedAtSlot(0))
+			throw T_Fail.testFailMsg("isDeletedAtSlot() doesn't represent correct state");
+
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("P003");
+	}
+
+	/**
+		Test Page.update
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+
+		@see Page#update
+	*/
+	protected void P004(long segment) throws StandardException, T_Fail {
+
+		Transaction t = t_util.t_startTransaction();		
+
+		long cid = t_util.t_addContainer(t, segment);
+
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		RecordHandle r1, r2;
+
+		T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
+		T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
+
+		r1 = t_util.t_insertAtSlot(page, 0, row1);
+		r2 = t_util.t_insertAtSlot(page, 1, row2);
+
+		t_util.t_checkFetch(page, r1, REC_001);
+		if (r2 != null)
+			t_util.t_checkFetch(page, r2, REC_002);
+
+		row1 = new T_RawStoreRow((String) null);
+		if (!page.update(r1, row1.getRow(), (FormatableBitSet) null))
+			throw T_Fail.testFailMsg("update() returned false");
+
+		t_util.t_checkFetch(page, r1, (String) null);
+		if (r2 != null)
+			t_util.t_checkFetch(page, r2, REC_002);
+
+		t_util.t_checkFetch(page, r1, (String) null);
+		if (r2 != null)
+			t_util.t_checkFetch(page, r2, REC_002);
+
+		row1 = new T_RawStoreRow(REC_003);
+		if (!page.update(r1, row1.getRow(), (FormatableBitSet) null))
+			throw T_Fail.testFailMsg("update() returned false");
+
+		t_util.t_checkFetch(page, r1, REC_003);
+		if (r2 != null)
+			t_util.t_checkFetch(page, r2, REC_002);
+
+		// now delete the record we have been updating
+		if (!page.delete(r1, (LogicalUndo)null))
+			throw T_Fail.testFailMsg("delete returned false");
+
+		row1 = new T_RawStoreRow(REC_004);
+		if (page.update(r1, row1.getRow(), (FormatableBitSet) null))
+			throw T_Fail.testFailMsg("update returned true on deleted record");
+
+		page.deleteAtSlot(0, false, (LogicalUndo)null);
+
+		t_util.t_checkFetch(page, r1, REC_003);
+
+		if (!page.update(r1, row1.getRow(), (FormatableBitSet) null))
+			throw T_Fail.testFailMsg("update returned false");
+
+		t_util.t_checkFetch(page, r1, REC_004);
+
+
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("P004");
+
+	}
+
+	/* test repeated insert */
+	protected void P005(long segment) throws StandardException, T_Fail 
+	{
+		Transaction t = t_util.t_startTransaction();		
+
+		long cid = t_util.t_addContainer(t, segment);
+
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
+		Page page1 = t_util.t_getLastPage(c);
+	
+		T_RawStoreRow row0 = new T_RawStoreRow
+			("long row xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx long row ");
+		T_RawStoreRow row1 = new T_RawStoreRow
+			("medium row yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy medium row");
+
+		t_util.t_insertAtSlot(page1, 0, row0);
+
+		int i = 0;
+		while (page1.spaceForInsert())
+		{
+			if (t_util.t_insertAtSlot(page1, 1, row1) == null)
+				break;
+			i++;
+		}
+
+		int count1 = page1.recordCount();
+
+		Page page2 = t_util.t_addPage(c);
+		t_util.t_insertAtSlot(page2, 0, row0);
+
+		i = 1;
+		while (page2.spaceForInsert())
+		{
+			if (t_util.t_insertAtSlot(page2, i++, row1) == null)
+				break;
+		}
+
+		int count2 = page2.recordCount();
+
+		// now purge them all and start over
+		page1.purgeAtSlot(1, page1.recordCount()-1, logDataForPurges);
+		page2.purgeAtSlot(1, page2.recordCount()-1, logDataForPurges);
+		if (page1.recordCount() != 1)
+			throw T_Fail.testFailMsg("purge did not clean up page");
+
+		if (page2.recordCount() != 1)
+			throw T_Fail.testFailMsg("purge did not clean up page");
+
+		i = 0;
+		while(page1.spaceForInsert())
+		{
+			if (t_util.t_insertAtSlot(page1, 1, row1) == null)
+				return;
+			i++;
+		}
+
+		if (page1.recordCount() != count1)
+			throw T_Fail.testFailMsg("cannot insert back same number of rows we purged");
+
+
+		i = 1;
+		while(page2.spaceForInsert())
+		{
+			if (t_util.t_insertAtSlot(page2, i++, row1) == null)
+				break;
+		}
+
+		if (page2.recordCount() != count2)
+			throw T_Fail.testFailMsg("cannot insert back same number of rows we purged");
+
+		page1.unlatch();
+		page2.unlatch();	
+
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("P005");
+	}
+
+	/*
+		P006
+
+		test page time stamp - make sure all operation changes page time stamp
+	*/
+	protected void P006() throws StandardException, T_Fail
+	{
+		Transaction t = t_util.t_startTransaction();
+		PageTimeStamp ts;
+
+		long cid = t_util.t_addContainer(t, 0);
+		t_util.t_commit(t);
+
+		ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
+		Page page1 = t_util.t_getLastPage(c);
+		
+		ts = page1.currentTimeStamp();
+		if (ts != null && !page1.equalTimeStamp(ts))
+			throw T_Fail.testFailMsg("page returns non-null time stamp which is not equal to its current time stamp");
+
+		T_RawStoreRow row = new T_RawStoreRow(REC_001);
+		RecordHandle rh = t_util.t_insert(page1, row);
+
+		if (page1.equalTimeStamp(ts))
+			throw T_Fail.testFailMsg("timestamp on page not changed after insert operation");
+		page1.setTimeStamp(ts);
+		if (ts != null && !page1.equalTimeStamp(ts))
+			throw T_Fail.testFailMsg("page returns non-null time stamp which is not equal to its current time stamp");
+
+		// failed update should not change time stamp
+		t_util.t_updateSlotOutOfRange(page1, 3);
+		if (ts != null && !page1.equalTimeStamp(ts))
+			throw T_Fail.testFailMsg("failed pdate should not change time stamp");
+
+		T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
+		page1.update(rh, row2.getRow(), (FormatableBitSet) null);
+		if (page1.equalTimeStamp(ts))
+			throw T_Fail.testFailMsg("timestamp on page not changed after update operation");
+
+		page1.setTimeStamp(ts);
+
+		T_RawStoreRow upd1 = new T_RawStoreRow(REC_003);
+		page1.update(rh, upd1.getRow(), BS_COL_0);
+		if (page1.equalTimeStamp(ts))
+			throw T_Fail.testFailMsg("timestamp on page not changed after update field operation");
+
+		page1.setTimeStamp(ts);
+
+		page1.delete(rh, (LogicalUndo)null);
+		if (page1.equalTimeStamp(ts))
+			throw T_Fail.testFailMsg("timestamp on page not changed after delete operation");
+
+		page1.setTimeStamp(ts);
+		
+		page1.purgeAtSlot(0, 1, logDataForPurges);
+		if (page1.equalTimeStamp(ts))
+			throw T_Fail.testFailMsg("timestamp on page not changed after delete operation");
+
+		page1.setTimeStamp(ts);
+		page1.unlatch();
+
+		if (testRollback)
+		{
+			t_util.t_abort(t);
+			c = t_util.t_openContainer(t, 0, cid, true);
+			page1 = t_util.t_getLastPage(c);
+
+			if (page1.equalTimeStamp(ts))
+				throw T_Fail.testFailMsg("timestamp on page not changed after rollback");
+
+			page1.setTimeStamp(ts);
+		}
+		
+		Page page2 = c.addPage();
+		Page page3 = c.addPage();
+
+		page2.setTimeStamp(ts);
+
+		if (ts != null)
+		{
+			try 
+			{
+				if (page3.equalTimeStamp(ts))
+					throw T_Fail.testFailMsg("timestamp on 2 different pages should not equate");
+			}
+			catch (StandardException se)
+			{
+				// either throw an exception or return false is OK
+			}
+		}
+
+
+		t_util.t_dropContainer(t, 0, cid);	// cleanup
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("P006");
+
+	}
+
+	/**
+		P007
+
+		this test exercises repeated updates on a 1K page
+
+		2 rows (with 1 column) will be inserted into the page.
+		We expand the row data in slot 0 by 1 byte until the page is completely full,
+		and overflows the record to an overflow page.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	  */
+
+	  protected void P007(long segment) throws StandardException, T_Fail {
+
+		Transaction t = t_util.t_startTransaction();		
+
+		// PART 1:
+		// insert two 1-column rows into the page, expand the first row, until it overflows.
+		long cid = t_util.t_addContainer(t, segment, 4096, 0, 1, false);
+
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
+		Page page = t_util.t_getLastPage(c);
+	
+		T_RawStoreRow row = new T_RawStoreRow(REC_001); // McLaren
+		T_RawStoreRow row2 = new T_RawStoreRow(new String(new char[300])); 
+
+		RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row);
+		RecordHandle r2 = t_util.t_insertAtSlot(page, 1, row2);
+
+		// update the row size 1 byte larger, until the page is full
+		String rowData = REC_001;
+		// 900 is an estimated number, because for 1K page,
+		// if you expand your row by 1 byte 900 times, the row will overflow for sure.
+		for (int i = 0; i <= 900; i++) {
+			t_util.t_checkFetch(page, r1, rowData);
+
+			rowData = rowData + REC_008;	// "z"
+			row = new T_RawStoreRow(rowData);
+			page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null);
+		}
+
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+
+		// PART 2:
+		// insert two 2-column rows into the page,
+		// expand the first row by expanding the first column by 300 bytes,
+		// and shrinking the second column by 300 bytes.  Update should secceed.
+		cid = t_util.t_addContainer(t, segment, 4096, 0, 1, false);
+		c = t_util.t_openContainer(t, segment, cid, true);
+		page = t_util.t_getLastPage(c);
+		long pid = page.getPageNumber();
+
+		row = new T_RawStoreRow(2);
+		row.setColumn(0, REC_001);	// small column
+		row.setColumn(1, new String (new char[400]));	// large column
+
+		r1 = t_util.t_insertAtSlot(page, 0, row);
+		r2 = t_util.t_insertAtSlot(page, 1, row2);
+
+		row.setColumn(0, REC_001 + new String (new char[300]));
+		row.setColumn(1, new String (new char[100]));
+
+		page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null);
+
+		Page page2 = t_util.t_addPage(c);
+		long pid2 = page2.getPageNumber();
+		if (pid2 != (pid + 1))
+			throw T_Fail.testFailMsg("The update should not have overflowed the record");
+
+		// Now, shrink the first column by 300 bytes, and expand the second column by 300 bytes.
+		// the update should also succeed.
+		row.setColumn(0, REC_001);
+		row.setColumn(1, new String (new char[400]));
+
+		page.updateAtSlot(0, row.getRow(), (FormatableBitSet) null);
+
+		Page page3 = t_util.t_addPage(c);
+		long pid3 = page3.getPageNumber();
+		if (pid3 != (pid2 + 1))
+			throw T_Fail.testFailMsg("The update should not have overflowed the record");
+
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("P007");
+
+	}
+
+	/**
+		P008
+
+		this test exercises repeated inserts with small rows on a 1K page
+
+		we will insert as many rows as possible into the page.  Then we reduce the row by 1 byte at a time,
+		we will try to insert another smaller row.
+		This test also tests spaceForInsert().
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	  */
+
+	protected void P008(long segment) throws StandardException, T_Fail 
+	{
+		Transaction t = t_util.t_startTransaction();		
+
+		long cid = t_util.t_addContainer(t, segment, 4096, 0, 1, false);
+
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
+		Page page1 = t_util.t_getLastPage(c);
+	
+		T_RawStoreRow row = new T_RawStoreRow(REC_001);		// McLaren
+
+		t_util.t_insertAtSlot(page1, 0, row);
+
+		int i = 0;
+		while (page1.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100))
+		{
+			// if it says there is enough room for this row, the insert should succeed.
+			if (t_util.t_insertAtSlot(page1, 1, row) == null)
+				throw T_Fail.testFailMsg("There is space for this insert.  It shouldn't have failed.  "
+					+ "record #" + i);
+			i++;
+		}
+
+		REPORT(i + " rows inserted.");
+
+		// We got out of the while loop because there is no room for the insert.
+		// So, if the insert succeed, then we have a problem.
+		if (t_util.t_insertAtSlot(page1, 1, row) != null)
+			throw T_Fail.testFailMsg("There is no space for this insert.  It should have failed.");
+
+		// Now, we will try to fill the page with smaller rows.
+		String[] s = new String[7];
+		s[6] = "McLare";
+		s[5] = "McLar";
+		s[4] = "McLa";
+		s[3] = "McL";
+		s[2] = "Mc";
+		s[1] = "M";
+		s[0] = null;
+		// reduce the row by 1 byte
+		i = 6;
+		boolean notDone = true;
+		do
+		{
+			row = new T_RawStoreRow(s[i]);
+			if (page1.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100))
+			{
+				// If it says there is enough room for the row, then the insert should succed.
+				if (t_util.t_insertAtSlot(page1, 1, row) == null)
+					throw T_Fail.testFailMsg("There should be space for this insert, row is " + s[i]);
+				else
+					notDone = false;
+			}
+			else
+				i--;
+		} while ((notDone) && (i >= 0));
+
+
+		page1.unlatch();
+
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("P008");
+	}
+
+	/**
+		P009
+
+		this test exercises repeated shrinking and expanding of fields using updateFieldBySlot
+
+		we will insert as many rows as possible into the page. Then set some of the columns to null,
+		That should not create more space on the page for inserts, because the extra space become
+		reservedspace for the row.  So, the next insert should fail.
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	  */
+
+	protected void P009(long segment) 
+		 throws StandardException, T_Fail 
+	{
+		int slot = 0;
+		int i = 0;
+		int j = 0;
+		String field = REC_001;
+
+		Transaction t = t_util.t_startTransaction();
+
+		long cid = t_util.t_addContainer(t, segment);
+
+		// Get the first page & check the record counts are zero
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		t_util.t_checkEmptyPage(page);
+
+		// Create a 13-column row
+		T_RawStoreRow row = new T_RawStoreRow(13);
+		row.setColumn(0, (String) null);
+		row.setColumn(1, REC_001);
+		row.setColumn(2, REC_002);
+		row.setColumn(3, REC_003);
+		row.setColumn(4, REC_004);
+		row.setColumn(5, REC_005);
+		row.setColumn(6, REC_006);
+		row.setColumn(7, REC_007);
+		row.setColumn(8, (String) null);
+		row.setColumn(9, (String) null);
+		row.setColumn(10, REC_007);
+		row.setColumn(11, (String) null);
+		row.setColumn(12, REC_006);
+
+		// insert the row into the page until the page is full
+		int numRows = 0;
+		slot = page.FIRST_SLOT_NUMBER;
+		while (page.spaceForInsert(row.getRow(), (FormatableBitSet) null, 100)) {
+			t_util.t_insert(page, row);
+			numRows++;
+		}
+		REPORT(numRows + " rows inserted ");
+
+		// update all the fields in the even number rows to null
+		// set all the fields in the odd number rows to REC_001
+		DataValueDescriptor col = new SQLChar();	// null
+		for (i = page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++) {
+
+			for (slot = i; slot <= (numRows - 1); slot += 2) {
+
+				for (j = 0; j <= 12; j++) {
+					if (page.updateFieldAtSlot(slot, j, col, null) == null) {
+
+						throw T_Fail.testFailMsg("Failed to update field " + j+ ", in row " + slot);
+					}
+				}
+			}
+
+			col = new SQLChar(REC_001);
+		}
+
+		// fetch all the fields, and see if they are correct
+		DataValueDescriptor storedColumn = new SQLChar();
+		field = null;
+		for (i = page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++) {
+
+			for (slot = i; slot <= (numRows - 1); slot += 2) {
+
+				for (j = 0; j <= 12; j++) {
+
+					t_util.t_checkFetchColFromSlot(page, slot, j, storedColumn, false, field);
+
+				}
+			}
+
+			field = REC_001;
+		}
+
+		// Now if we try to insert the old row again, there should still be no room
+		if (page.spaceForInsert())
+			throw T_Fail.testFailMsg("Did not get no room for record on page error");
+
+		// update the first and last field of every row to REC_006
+		col = new SQLChar(REC_006);
+		for (slot = page.FIRST_SLOT_NUMBER; slot <= (numRows - 1); slot++) {
+			if (page.updateFieldAtSlot(slot, 0, col, null) == null ||
+					page.updateFieldAtSlot(slot, 12, col, null) == null) {
+
+				throw T_Fail.testFailMsg("Failed to update fields to REC_006 in row " + slot);
+			}
+		}
+		
+		// update field 5 and 6 of every row to REC_007
+		col = new SQLChar(REC_007);
+		for (slot = page.FIRST_SLOT_NUMBER; slot <= (numRows - 1); slot++) {
+			if (page.updateFieldAtSlot(slot, 5, col, null) == null ||
+					page.updateFieldAtSlot(slot, 6, col, null) == null) {
+
+				throw T_Fail.testFailMsg("Failed to update fields to REC_007 in row " + slot);
+			}
+		}
+
+		// fetch all the fields again, and see if they are correct
+		for (i = page.FIRST_SLOT_NUMBER; i < (page.FIRST_SLOT_NUMBER + 2); i++) {
+
+			for (slot = i; slot <= (numRows - 1); slot += 2) {
+
+				for (j = 0; j <= 12; j++) {
+
+					switch (j) {
+					case 0:
+					case 12:
+						field = REC_006;
+						break;
+					case 5:
+					case 6:
+						field = REC_007;
+						break;
+					default:
+						if ((slot % 2) == 0)
+							field = null;
+						else
+							field = REC_001;
+						break;
+					}
+
+					t_util.t_checkFetchColFromSlot(page, slot, j, storedColumn, false, field);
+
+				}
+			}
+		}
+
+		// We now try to insert the old row one last time, there should still be no room
+		if (page.spaceForInsert())
+			throw T_Fail.testFailMsg("Did not get no room for record on page error");
+
+		// now we want to increase row 0 and column 5 one byte at a time, until the page is full
+		// but, every 5 increases we will reduce the field size by one byte
+		field = REC_007;
+		i = 0;
+		String field_pre = null;
+		while (true) {
+			if ((i % 5) != 0) {
+				field_pre = field;
+				field += REC_008;
+			} else {
+				field = field_pre;
+			}
+
+			if (((i % 10) == 3) || ((i % 10) == 7)) {
+				page.unlatch();
+				page = null;
+
+				factory.idle();
+
+				page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+			}
+
+			col = new SQLChar(field);
+
+			try {
+				page.updateFieldAtSlot(0, 5, col, null);
+			} catch (StandardException se) {
+				// now we have filled the page
+				if (i < 809) {
+					throw T_Fail.testFailMsg("should be able to update Row 0 Column 5 809 times"
+						+ ", but only updated " + i
+						+ " times.  Note: you maybe getting this error if your page format has changed.");
+				} else {
+					REPORT("Row 0 Column 5 was updated " + i + " times.");
+				}
+				break;
+			}
+			i++;
+		}
+		
+		// The page is completely full at this point.
+		// update Row 1 Column 1 from REC_001 to REC_002.  They are the same length
+		page.unlatch();
+		page = null;
+		factory.idle();
+		page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+		col = new SQLChar(REC_002);
+		if (page.updateFieldAtSlot(1, 1, col, null) == null) {
+			throw T_Fail.testFailMsg("update Row 1 and Column 1 to same length data failed.");
+		}
+
+		REPORT("updated col1 in row 1 to same length");
+
+		// now expand update Row 1 Column 1 by one byte.  This should fail.
+		page.unlatch();
+		page = null;
+		factory.idle();
+		page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+		field = REC_002 + REC_008;
+		col = new SQLChar(field);
+		try {
+			page.updateFieldAtSlot(1, 1, col, null);
+			throw T_Fail.testFailMsg("update Row 1 and Column 1 to longer length should have failed.");
+		} catch (StandardException se) {
+			;
+		}
+
+
+		// clean up
+		if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
+			t_util.t_dropContainer(t, segment, cid);	// cleanup
+		}
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("P009: segment " + segment);
+		
+	}
+
+
+
+	/**
+		P011
+
+		this test exercises insertAtSlot, (LogicalUndo)null
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	  */
+	protected void P011(long segment)
+		 throws StandardException, T_Fail
+	{
+		Transaction t = t_util.t_startTransaction();
+		long cid = t_util.t_addContainer(t, segment);
+		t_util.t_commit(t);
+
+	
+		// Get the first page
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		// REPORT("insert 2 records at FIRST_SLOT_NUMBER");
+		T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
+		T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
+		T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
+		T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
+
+		// try inserting at slot -1 and slot 1
+		try {
+			RecordHandle r = t_util.t_insertAtSlot(page, -1, row1);
+			throw T_Fail.testFailMsg("insert at slot -1 succeeded");
+		} catch (StandardException se) {
+			// throw if not a statement exception.
+            if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                throw se;
+		}
+
+		try {
+			RecordHandle r = t_util.t_insertAtSlot(page, 1, row1);
+			throw T_Fail.testFailMsg("insert at slot 1 succeeded");
+		} catch (StandardException se) {
+			// throw if not a statement exception.
+            if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                throw se;
+		}
+		
+		RecordHandle r1, r2, r3, r4;
+		// first insert to a page must suceed
+		r3 = t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER, row3);
+		t_util.t_checkFetch(page, r3, REC_003);
+		t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER, REC_003,false, false);			
+
+		r1 = r2 = r4 = null;
+		r1 = t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER, row1);
+
+		if (r1 != null) {
+			t_util.t_checkFetch(page, r1, REC_001);
+			t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER, REC_001,false, false);
+		} else {
+			t_util.t_abort(t);
+			t.close();
+			REPORT("P011 not run - could not fit 4 rows on page");
+			return;
+		}
+
+		// REPORT("insert a record at 2nd slot");
+		r2 = t_util.t_insertAtSlot(page, Page.FIRST_SLOT_NUMBER+1, row2);
+
+		if (r2 != null) {
+			t_util.t_checkFetch(page, r2, REC_002);
+			t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+1, REC_002,false, false);
+		} else {
+			t_util.t_abort(t);
+			t.close();
+			REPORT("P011 not completed - could not fit 4 rows on page");
+			return;
+		}
+
+		// REPORT("insert a record at the end");
+		r4 = t_util.t_insertAtSlot(page, 3, row4);
+		if (r4 != null) {
+			t_util.t_checkFetch(page, r4, REC_004);
+			t_util.t_checkFetchBySlot(page, 3, REC_004,false, false);
+		} else {
+			t_util.t_abort(t);
+			t.close();
+			REPORT("P011 not completed - could not fit 4 rows on page");
+			return;
+		}
+
+		// REPORT("make sure records are in the correct order");
+		// order is REC_001 REC_002 REC_003 REC_004 
+
+
+		t_util.t_checkFetchFirst(page, REC_001);
+		t_util.t_checkFetchNext(page, r1, REC_002);
+		t_util.t_checkFetchNext(page, r2, REC_003);
+		t_util.t_checkFetchNext(page, r3, REC_004);
+		t_util.t_checkFetchLast(page, REC_004);
+
+		// check the fetch by slot interface
+		t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER, REC_001,false, true);
+		t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+1, REC_002,false, false);
+		t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+2, REC_003,false, true);
+		t_util.t_checkFetchBySlot(page, Page.FIRST_SLOT_NUMBER+3, REC_004,false, false);
+
+		// clean up
+
+		t_util.t_dropContainer(t, segment, cid);	// cleanup
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("P011");
+
+	}
+
+	/**
+	  P012
+
+	  this test exercises updateAtSlot
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void P012(long segment)
+		 throws StandardException, T_Fail
+	{
+		Transaction t = t_util.t_startTransaction();
+		long cid = t_util.t_addContainer(t, segment);
+
+		ContainerHandle c = t_util.t_openContainer(t, segment, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		// REPORT("insert 3 records");
+		T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
+
+		T_RawStoreRow row2 = new T_RawStoreRow(2);
+		row2.setColumn(0, (String) null);
+		row2.setColumn(1, REC_001);
+
+		T_RawStoreRow row3 = new T_RawStoreRow(3);
+		row3.setColumn(0, REC_001);
+		row3.setColumn(1, REC_002);
+		row3.setColumn(2, REC_003);
+
+		RecordHandle r1, r2, r3;
+		r1 = t_util.t_insertAtSlot(page, 0, row1);
+
+		r2 = r3 = null;
+		r2 = t_util.t_insertAtSlot(page, 1, row2);
+	
+		if (r2 == null) {
+			REPORT("P012 not completed - cannot insert second row");
+			return;
+		}
+
+		r3 = t_util.t_insertAtSlot(page, 2, row3);
+		if (r3 == null) {
+			REPORT("P012 not completed - cannot insert third row");
+			return;
+		}
+
+		// check that they are inserted correctly
+		t_util.t_checkFetch(page, r1, row1);
+		t_util.t_checkFetch(page, r2, row2);
+		t_util.t_checkFetch(page, r3, row3);
+
+		// REPORT("update that grows the #columns in row");
+		T_RawStoreRow upd1 = new T_RawStoreRow(2);
+		upd1.setColumn(0, (String) null);
+		upd1.setColumn(1, REC_001);
+
+		r1 = page.updateAtSlot(0, upd1.getRow(), (FormatableBitSet) null);
+		t_util.t_checkFetch(page, r1, upd1);
+		t_util.t_checkFetch(page, r2, row2);
+		t_util.t_checkFetch(page, r3, row3);
+
+		// REPORT("update that shrinks the #columns in row");
+		T_RawStoreRow upd2 = new T_RawStoreRow(REC_004);
+
+		r2 = page.updateAtSlot(1, upd2.getRow(), (FormatableBitSet) null);
+		t_util.t_checkFetch(page, r1, upd1);
+		t_util.t_checkFetch(page, r2, upd2);
+		t_util.t_checkFetch(page, r3, row3);
+
+		// REPORT("update same #columns in row");
+		T_RawStoreRow upd3 = new T_RawStoreRow(3);
+		upd3.setColumn(0, REC_003);
+		upd3.setColumn(1, REC_002);
+		upd3.setColumn(2, REC_001);
+
+		r3 = page.updateAtSlot(2, upd3.getRow(), (FormatableBitSet) null);
+		t_util.t_checkFetch(page, r1, upd1);
+		t_util.t_checkFetch(page, r2, upd2);
+		t_util.t_checkFetch(page, r3, upd3);
+
+		// clean up
+
+		if (segment != ContainerHandle.TEMPORARY_SEGMENT) {
+			t_util.t_dropContainer(t, segment, cid);	// cleanup
+		}
+
+		t_util.t_commit(t);
+		t.close();
+
+		PASS("P012");
+	}
+
+	/**
+	  P013
+
+	  this test exercises deleteAtSlot and isDeletedAtSlot
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void P013()
+		 throws StandardException, T_Fail
+	{
+		Transaction t = t_util.t_startTransaction();
+		long cid = t_util.t_addContainer(t, 0);
+
+		t_util.t_commit(t);
+
+		ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		// REPORT("insert 2 records");
+		T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
+		T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
+
+		RecordHandle r1 = t_util.t_insertAtSlot(page, 0, row1);
+		RecordHandle r2;
+		r2 = t_util.t_insertAtSlot(page, 1, row2);
+		if (r2 == null) {
+			REPORT("P013 not completed - could not fit two rows on a page");
+			return;
+		}
+
+		t_util.t_checkRecordCount(page, 2, 2);
+
+		// REPORT("delete them one by one");
+		page.deleteAtSlot(0, true, (LogicalUndo)null);
+
+		t_util.t_checkRecordCount(page, 2, 1);
+
+		if (!page.isDeletedAtSlot(0))
+			throw T_Fail.testFailMsg("Failed to delete record 0");
+		if (page.isDeletedAtSlot(1))
+			throw T_Fail.testFailMsg("Record mistakenly deleted");
+
+		page.deleteAtSlot(1, true, (LogicalUndo)null);
+		t_util.t_checkRecordCount(page, 2, 0);
+		if (!page.isDeletedAtSlot(1))
+			throw T_Fail.testFailMsg("Failed to delete record 1");
+
+		page.deleteAtSlot(0, false, (LogicalUndo)null);
+		t_util.t_checkRecordCount(page, 2, 1);
+		if (page.isDeletedAtSlot(0))
+			throw T_Fail.testFailMsg("Failed to undelete record 0");
+		if (!page.isDeletedAtSlot(1))
+			throw T_Fail.testFailMsg("Record mistakenly undeleted");
+
+		page.deleteAtSlot(1, false, (LogicalUndo)null);
+		t_util.t_checkRecordCount(page, 2, 2);
+		if (page.isDeletedAtSlot(1))
+			throw T_Fail.testFailMsg("Failed to undelete record 1");
+
+		// try the negative tests
+		try {
+			page.deleteAtSlot(0, false, (LogicalUndo)null);
+			throw T_Fail.testFailMsg("undeleted on undeleted record succeeded");
+		} catch (StandardException se) {
+			// throw if not a statement exception.
+            if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                throw se;
+		}
+
+		page.deleteAtSlot(0, true, (LogicalUndo)null);
+		try {
+			page.deleteAtSlot(0, true, (LogicalUndo)null);
+			throw T_Fail.testFailMsg("deleted on deleted record succeeded");
+		} catch (StandardException se) {
+			// throw if not a statement exception.
+            if (se.getSeverity() > ExceptionSeverity.STATEMENT_SEVERITY)
+                throw se;
+		}
+
+		t_util.t_checkRecordCount(page, 2, 1);
+		// clean up
+		PASS("P013");
+
+		t_util.t_dropContainer(t, 0, cid);	// cleanup
+
+
+
+		t_util.t_commit(t);
+		t.close();
+
+		
+	}
+
+	/**
+	  P014
+
+	  this test exercises purgeAtSlot
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void P014()
+		 throws StandardException, T_Fail
+	{
+		Transaction t = t_util.t_startTransaction();
+		long cid = t_util.t_addContainer(t,0);
+		t_util.t_commit(t);
+
+	
+		ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		// REPORT("insert 5 records");
+		T_RawStoreRow row0 = new T_RawStoreRow(REC_001);
+		T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
+		T_RawStoreRow row2 = new T_RawStoreRow(REC_002);
+		T_RawStoreRow row3 = new T_RawStoreRow(REC_003);
+		T_RawStoreRow row4 = new T_RawStoreRow(REC_004);
+		
+		RecordHandle r0, r1, r2, r3, r4;
+		r0 = t_util.t_insertAtSlot(page, 0, row0);
+		r1 = t_util.t_insertAtSlot(page, 1, row1);
+		r2 = t_util.t_insertAtSlot(page, 2, row2);
+		r3 = t_util.t_insertAtSlot(page, 3, row3);
+		r4 = t_util.t_insertAtSlot(page, 4, row4);
+
+		if (r3 != null) page.deleteAtSlot(3, true, (LogicalUndo)null);
+
+		// REPORT("commit it");
+		t_util.t_commit(t);
+
+		c = t_util.t_openContainer(t, 0, cid, true);
+		page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		try 
+		{
+			page.purgeAtSlot(-1, 1, logDataForPurges);
+			throw T_Fail.testFailMsg("negative slot number did not cause an exception");
+		}
+		catch (StandardException se) {}	// expected
+
+		try
+		{
+			page.purgeAtSlot(4, 4, logDataForPurges);
+			throw T_Fail.testFailMsg("purging more rows than is on page did not cause an exception");
+		}
+		catch (StandardException se) {}	// expected
+
+		// if not all the rows are there, do minimal test
+		if (r4 == null)
+		{
+			int rcount = page.recordCount();
+			page.purgeAtSlot(0, 1, logDataForPurges);
+			if (page.recordCount() != rcount-1)
+				T_Fail.testFailMsg("failed to purge a record, expect " + 
+								   (rcount-1) + " got " + page.recordCount());
+
+			if (testRollback)
+			{
+				t_util.t_abort(t);
+
+				c = t_util.t_openContainer(t, 0, cid, true);
+				page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+				if(logDataForPurges)
+					t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
+				else
+					t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
+				if (page.recordCount() != rcount)
+					T_Fail.testFailMsg("failed to rollback purge, expect " + 
+								   rcount + " got " + page.recordCount());
+			}
+			else
+			{
+				t_util.t_commit(t);
+			}
+			PASS("minimal P014");
+			return;
+		}
+
+		// REPORT("purge 2 records from middle");
+		page.purgeAtSlot(1, 2, logDataForPurges);
+		t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
+		t_util.t_checkFetchBySlot(page, 1, REC_003,true, true);
+		t_util.t_checkFetchBySlot(page, 2, REC_004,false, true);
+
+		if (page.recordCount() != 3)
+			T_Fail.testFailMsg("page expect to have 3 records, recordCount() = " +
+							   page.recordCount());
+
+		// REPORT("purge all records from the page");
+		page.purgeAtSlot(0, 3, logDataForPurges);
+		if (page.recordCount() != 0)
+			T_Fail.testFailMsg("page expect to have 0 records, recordCount() = " +
+							   page.recordCount());
+
+		if (testRollback)
+		{
+
+			REPORT("testing rollback");
+			t_util.t_abort(t);
+
+			c = t_util.t_openContainer(t, 0, cid, true);
+			page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+			if(logDataForPurges){
+				t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
+				t_util.t_checkFetchBySlot(page, 1, REC_001,false, true);
+				t_util.t_checkFetchBySlot(page, 2, REC_002,false, true);
+				t_util.t_checkFetchBySlot(page, 3, REC_003,true, true);
+				t_util.t_checkFetchBySlot(page, 4, REC_004,false, true);
+			}else
+			{
+				t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
+				t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
+				t_util.t_checkFetchBySlot(page, 2, REC_NULL,false, true);
+				t_util.t_checkFetchBySlot(page, 3, REC_NULL,true, true);
+				t_util.t_checkFetchBySlot(page, 4, REC_NULL,false, true);
+			}
+
+			if (page.recordCount() != 5)
+				T_Fail.testFailMsg("page expect to have 5 records, recordCount() = " +
+								   page.recordCount());
+
+			// REPORT("purge 3 records from the end");
+			page.purgeAtSlot(2, 3, logDataForPurges);
+			if(logDataForPurges)
+			{
+				t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
+				t_util.t_checkFetchBySlot(page, 1, REC_001,false, true);
+			}else
+			{
+				t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
+				t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
+			}
+			if (page.recordCount() != 2)
+				T_Fail.testFailMsg("page expect to have 2 records, recordCount() = " +
+								   page.recordCount());
+
+			// REPORT("rollback");
+			t_util.t_abort(t);
+
+			c = t_util.t_openContainer(t, 0, cid, true);
+			page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+			if(logDataForPurges){
+				t_util.t_checkFetchBySlot(page, 0, REC_001,false, true);
+				t_util.t_checkFetchBySlot(page, 1, REC_001,false, true);
+				t_util.t_checkFetchBySlot(page, 2, REC_002,false, true);
+				t_util.t_checkFetchBySlot(page, 3, REC_003,true, true);
+				t_util.t_checkFetchBySlot(page, 4, REC_004,false, true);
+			}else
+			{
+				t_util.t_checkFetchBySlot(page, 0, REC_NULL,false, true);
+				t_util.t_checkFetchBySlot(page, 1, REC_NULL,false, true);
+				t_util.t_checkFetchBySlot(page, 2, REC_NULL,false, true);
+				t_util.t_checkFetchBySlot(page, 3, REC_NULL,true, true);
+				t_util.t_checkFetchBySlot(page, 4, REC_NULL,false, true);	
+			}
+
+			if (page.recordCount() != 5)
+				T_Fail.testFailMsg("page expect to have 5 records, recordCount() = " +
+								   page.recordCount());
+
+			// REPORT("make sure delete record is reconstituted as such");
+			if (page.isDeletedAtSlot(1))
+				T_Fail.testFailMsg("rolled back purged undeleted record cause record to be deleted");
+			if (!page.isDeletedAtSlot(3))
+				T_Fail.testFailMsg("rolled back purged deleted record cause record to be undeleted");
+		}
+		PASS("P014");
+
+		t_util.t_dropContainer(t, 0, cid);	// cleanup
+		t_util.t_commit(t);
+		t.close();
+	}
+
+
+	/**
+	  P015
+
+	  this test exercises updateAtSlot
+
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void P015()
+		 throws StandardException, T_Fail
+	{
+		Transaction t = t_util.t_startTransaction();
+		long cid = t_util.t_addContainer(t, 0);
+
+		t_util.t_commit(t);
+
+
+		ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
+		Page page = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+
+		// REPORT("insert 3 records");
+		T_RawStoreRow row1 = new T_RawStoreRow(REC_001);
+
+		T_RawStoreRow row2 = new T_RawStoreRow(2);
+		row2.setColumn(0, (String) null);
+		row2.setColumn(1, REC_001);
+
+		T_RawStoreRow row3 = new T_RawStoreRow(3);
+		row3.setColumn(0, REC_001);
+		row3.setColumn(1, REC_002);
+		row3.setColumn(2, REC_003);
+
+		RecordHandle r1, r2, r3;
+		r1 = t_util.t_insertAtSlot(page, 0, row1);
+
+		r2 = r3 = null;
+		r2 = t_util.t_insertAtSlot(page, 1, row2);
+
+		if (r2 == null) {
+			REPORT("P015 not completed - cannot insert second row");
+			return;
+		}
+
+		r3 = t_util.t_insertAtSlot(page, 2, row3);
+
+		if (r3 == null) {
+			REPORT("P015 not completed - cannot insert third row");
+			return;
+		}
+
+		// check that they are inserted correctly
+		t_util.t_checkFetch(page, r1, row1);
+		t_util.t_checkFetch(page, r2, row2);
+		t_util.t_checkFetch(page, r3, row3);
+
+		// now update the middle row with a large value
+		T_RawStoreRow row2u = new T_RawStoreRow(2);
+		row2u.setColumn(0, "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
+		row2u.setColumn(1, "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
+
+		page.updateAtSlot(1, row2u.getRow(), (FormatableBitSet) null);
+		t_util.t_checkFetch(page, r2, row2u);
+
+
+		// now update the field of the first record with a large value
+		((T_RawStoreRow) row1).setColumn(0, "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
+
+        FormatableBitSet validColumn = new FormatableBitSet(2);
+
+        validColumn.clear();
+        validColumn.set(0);
+
+        page.updateAtSlot(0, row1.getRow(), validColumn);
+
+		t_util.t_checkFetch(page, r1, row1);
+
+		((T_RawStoreRow) row3).setColumn(1, "XXabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz");
+
+        validColumn.clear();
+        validColumn.set(1);
+
+        page.updateAtSlot(2, row3.getRow(), validColumn);
+		t_util.t_checkFetch(page, r3, row3);
+
+		// clean up
+		PASS("P015");
+
+		t_util.t_dropContainer(t, 0, cid);	// cleanup
+
+
+		t_util.t_commit(t);
+		t.close();
+
+	}
+
+	/*
+		P016
+
+		this test exercises copyAndPurge
+		@exception T_Fail Unexpected behaviour from the API
+		@exception StandardException Unexpected exception from the implementation
+	*/
+	protected void P016()
+		 throws StandardException, T_Fail
+	{
+		Transaction t = t_util.t_startTransaction();
+		long cid = t_util.t_addContainer(t, 0);
+		long cid2 = t_util.t_addContainer(t, 0);
+
+		t_util.t_commit(t);
+
+
+		ContainerHandle c = t_util.t_openContainer(t, 0, cid, true);
+
+		Page page1 = t_util.t_getPage(c, ContainerHandle.FIRST_PAGE_NUMBER);
+		Page page2 = t_util.t_addPage(c);
+		long pid1 = page1.getPageNumber();
+		long pid2 = page2.getPageNumber();
+
+		t_util.t_checkEmptyPage(page2);
+
+		// first fill up page 1
+
+		int i = 0;
+		int deleted = 0;
+		RecordHandle rh;
+
+		T_RawStoreRow row;
+
+		for (i = 0, row = new T_RawStoreRow("row at slot " + i);
+			 page1.spaceForInsert();

[... 4703 lines stripped ...]


Mime
View raw message