persistentstorage/dbms/tdbms/t_dbsrv.cpp
changeset 0 08ec8eefde2f
child 23 26645d81f48d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/persistentstorage/dbms/tdbms/t_dbsrv.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,1334 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+#include <d32dbms.h>
+#include <s32file.h>
+#include <e32test.h>
+#include <e32math.h>
+#include <hal.h>
+#include "D32DBAS.H"
+
+LOCAL_D RTest test(_L("t_dbsrv: Test DBMS server"));
+LOCAL_D CTrapCleanup* TheTrapCleanup;
+LOCAL_D RFs TheFs;
+LOCAL_D RDbs TheDbs;
+LOCAL_D RDbNamedDatabase TheDatabase;
+LOCAL_D RDbTable TheTable;
+LOCAL_D RDbView TheView;
+
+const TInt KTestCleanupStack=0x40;
+const TPtrC KTestDatabase(_S("c:\\dbms-tst\\share.db"));
+const TPtrC KTestFormat(_S(""));
+const TPtrC KTable1(_S("Table1"));
+const TPtrC KTable2(_S("Table2"));
+const TInt KRowCount=1000;
+const TUint KExitDelay=6*0x100000;	// ~6 seconds
+
+const TPtrC KCreateTable1=_S("CREATE TABLE Table1 (Id INTEGER,Name CHAR(200),Memo LONG VARCHAR,Memo2 LONG VARBINARY)");
+const TPtrC KCreateTable2=_S("CREATE TABLE Table2 (Id INTEGER,Name CHAR(200),Memo LONG VARCHAR)");
+const TPtrC KDropTable1=_S("DROP TABLE Table1");
+const TPtrC KDropTable2=_S("DROP TABLE Table2");
+
+_LIT(KTestSpdFile1, "c:\\dbms-tst\\11335577.spd");
+_LIT(KTestSpdFile2, "c:\\dbms-tst\\11335578.spd");
+_LIT(KTestSpdFile3, "c:\\dbms-tst\\11335579.spd");
+_LIT(KTestSpdFile4, "c:\\dbms-tst\\1133557A.spd");
+
+const TInt KReturnValueForCompare = 10;
+const TInt KReturnValueForFind = 20;
+
+class TTimer
+	{
+public:
+	void Start(const TDesC& aDes);
+	void Stop();
+private:
+	TUint iTicks;
+	};
+
+static TTimer TheTimer;
+
+void TTimer::Start(const TDesC& aDes)
+	{
+	test.Printf(_L("  %S: "),&aDes);
+	iTicks=User::FastCounter();
+	}
+
+void TTimer::Stop()
+	{
+	TUint ticks = User::FastCounter() - iTicks;
+	TInt freq = 0;
+	test(HAL::Get(HAL::EFastCounterFrequency, freq) == KErrNone);
+	const TInt KMicroSecIn1Sec = 1000000;
+	const TInt KMsIn1Sec = 1000;
+	double v = ((double)ticks * KMicroSecIn1Sec) / (double)freq; TInt v2 = (TInt)v;
+	test.Printf(_L("%d ms\r\n"),v2/KMsIn1Sec);
+	}
+
+void DeleteTestFiles()
+	{
+	(void)TheFs.Delete(KTestDatabase);
+	(void)TheFs.Delete(KTestSpdFile1); 
+	(void)TheFs.Delete(KTestSpdFile2); 
+	(void)TheFs.Delete(KTestSpdFile3); 
+	(void)TheFs.Delete(KTestSpdFile4); 
+	}
+
+void Check(TInt aValue,TInt aExpected,TInt aLine)
+	{
+	if (aValue!=aExpected)
+		{
+		DeleteTestFiles();
+		test.Printf(_L("*** Expected %d: got %d\r\n"),aExpected,aValue);
+		test.operator()(EFalse,aLine);
+		}
+	}
+#define test2(a,b) Check(a,b,__LINE__)
+
+LOCAL_C void Connect()
+	{
+	test2(TheDbs.Connect(),KErrNone);
+	TheDbs.ResourceMark();
+	}
+
+LOCAL_C void Disconnect()
+	{
+	TheDbs.ResourceCheck();
+	TheDbs.Close();
+	}
+
+LOCAL_C void Execute(const TDesC& aSql)
+	{
+	test2 (TheDatabase.Execute(aSql),KErrNone);
+	}
+
+LOCAL_C void WriteRecordsL(TInt aCount)
+	{
+	TheTimer.Start(_L("writing"));
+	TheDatabase.Begin();
+	TBuf<10> text;
+	TInt jj=0;
+	for (TInt ii=0;ii<aCount;++ii)
+		{
+		TheTable.InsertL();
+		jj=(jj+23);
+		if (jj>=aCount)
+			jj-=aCount;
+		TheTable.SetColL(1,jj);
+		text.Num(jj);
+		TheTable.SetColL(2,text);
+		TheTable.PutL();
+		}
+	test2 (TheDatabase.Commit(),KErrNone);
+	TheTimer.Stop();
+	}
+
+LOCAL_C void Ipc(TInt aCount)
+	{
+	TheTimer.Start(_L("ipc"));
+	while (--aCount>=0)
+		TheDatabase.InTransaction();
+	TheTimer.Stop();
+	}
+
+LOCAL_C void LoopL(RDbTable::TPosition aDirection)
+	{
+	TheTimer.Start(_L("loop"));
+	TInt cc=0;
+	while (TheTable.GotoL(aDirection))
+		++cc;
+	test2 (cc,TheTable.CountL());
+	TheTimer.Stop();
+	}
+
+LOCAL_C void IterateL(RDbTable::TPosition aDirection)
+	{
+	TheTimer.Start(_L("iterate"));
+	TInt cc=0;
+	while (TheTable.GotoL(aDirection))
+		{
+		++cc;
+		TheTable.GetL();
+		TBuf<10> text;
+		text.Num(TheTable.ColInt(1));
+		test (text==TheTable.ColDes(2));
+		}
+	test2 (cc,TheTable.CountL());
+	TheTimer.Stop();
+	}
+
+LOCAL_C void LocateL(const TDesC& aSql)
+	{
+	test2 (TheView.Prepare(TheDatabase,aSql),KErrNone);
+	test2 (TheView.EvaluateAll(),KErrNone);
+	TheTimer.Start(_L("locate"));
+	test (!TheView.NextL());
+	TheTimer.Stop();
+	TheView.Close();
+	}
+
+LOCAL_C void Locate1L()
+	{
+	LocateL(_L("select * from Table1 where id is null"));
+	}
+
+LOCAL_C void Locate2L()
+	{
+	LocateL(_L("select * from Table1 where id = -12345"));
+	}
+
+LOCAL_C TInt DeleteL()
+	{
+	TheTimer.Start(_L("deleting"));
+	TheDatabase.Begin();
+	TInt cc=0;
+	TheTable.BeginningL();
+	while (TheTable.NextL())
+		{
+		++cc;
+		TheTable.DeleteL();
+		}
+	test (TheTable.CountL()==0);
+	test (TheDatabase.Commit()==KErrNone);
+	TheTimer.Stop();
+	return cc;
+	}
+
+LOCAL_C TInt DeleteSQL()
+	{
+	TheTimer.Start(_L("deleting [SQL]"));
+	TInt cc=TheDatabase.Execute(_L("delete from Table1"));
+	test (cc>=KErrNone);
+	test (TheTable.CountL()==0);
+	TheTimer.Stop();
+	return cc;
+	}
+
+LOCAL_C void BenchmarkL()
+	{
+	TInt r=TheTable.Open(TheDatabase,KTable1);
+	TheTable.LastL();
+	test (r==KErrNone);
+	Ipc(KRowCount);
+	TheTable.Reset();
+	LoopL(TheTable.ENext);
+	TheTable.Reset();
+	IterateL(TheTable.ENext);
+	Locate1L();
+	Locate2L();
+	TheTable.Close();
+	}
+
+const TPtrC KSemaphore(_S("Connect-test"));
+
+LOCAL_C TInt ConnectThread(TAny*)
+	{
+	RSemaphore s;
+	s.OpenGlobal(KSemaphore,EOwnerThread);
+	RDbs dbs;
+	dbs.Connect();
+	s.Signal();
+	User::After(0x100000);
+	s.Wait();
+	dbs.Close();
+	s.Signal();
+	s.Close();
+	return KErrNone;
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0605
+@SYMTestCaseDesc        Single and multiple database connection tests
+@SYMTestPriority        Medium
+@SYMTestActions         Setup a DBMS server session Search the server for pattern matching
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void TestConnect()
+	{
+	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0605 Single connection "));
+	test (TheDbs.Connect()==KErrNone);
+	TheDbs.Close();
+	test.Next(_L("Deferred exit"));
+	TFindServer find(_L("!DBMS server"));
+	TFullName result;
+	test2 (find.Next(result),KErrNone);
+	test.Next(_L("Multiple connection"));
+	Connect();
+	RDbs dbs;
+	test2 (dbs.Connect(),KErrNone);
+	Disconnect();
+	dbs.Close();
+	test.Next(_L("Deferred exit"));
+	find.Find(_L("!DBMS server"));
+	test2 (find.Next(result),KErrNone);
+	User::After(KExitDelay);
+	find.Find(_L("!DBMS server"));
+	test2 (find.Next(result),KErrNotFound);
+	test.Next(_L("multiple thread connections"));
+	RSemaphore s;
+	test2 (s.CreateGlobal(KSemaphore,0,EOwnerThread),KErrNone);
+	RThread t;
+	test2 (t.Create(KSemaphore,ConnectThread,0x2000,0x1000,0x10000,0,EOwnerThread),KErrNone);
+	t.Resume();
+	TRequestStatus st;
+	t.Logon(st);
+	t.Close();
+	s.Wait();
+	Connect();
+	s.Signal();
+	s.Close();
+	User::WaitForRequest(st);
+	test2 (TheDbs.ResourceCount(),0);
+	Disconnect();
+	test.Next(_L("Deferred exit"));
+	find.Find(_L("!DBMS server"));
+	test2 (find.Next(result),KErrNone);
+	User::After(KExitDelay);
+	find.Find(_L("!DBMS server"));
+	test2 (find.Next(result),KErrNotFound);
+	test.End();
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0606
+@SYMTestCaseDesc        Tests for benchmark
+@SYMTestPriority        Medium
+@SYMTestActions         Tests for creating database and writing a table.Test for no error conditions.
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void TestBenchL()
+	{
+	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0606 Create database "));
+	TInt r=TheDatabase.Replace(TheFs,KTestDatabase,KTestFormat);
+	test (r==KErrNone);
+	Execute(KCreateTable1);
+	test.Next(_L("write table"));
+	r=TheTable.Open(TheDatabase,KTable1);
+	test (r==KErrNone);
+	WriteRecordsL(KRowCount);
+	TheTable.Close();
+	test.Next(_L("BenchmarkL"));
+	TRAPD(errCode, BenchmarkL());
+	test(errCode == KErrNone);
+	test.Next(_L("Open server-side"));
+	TheDatabase.Close();
+	Connect();
+	r=TheDatabase.Open(TheDbs,KTestDatabase);
+	test (r==KErrNone);
+	test.Next(_L("BenchmarkL"));
+	TRAP(errCode, BenchmarkL());
+	test(errCode == KErrNone);
+	test.Next(_L("Wrap up"));
+	TheDatabase.Close();
+	Disconnect();
+	test.End();
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0607
+@SYMTestCaseDesc        Tests for opening a shared database
+@SYMTestPriority        Medium
+@SYMTestActions         Tests for database open,column type,write and drop table
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void TestOpenL()
+	{
+	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0607 Create database "));
+	test2 (TheDatabase.Replace(TheFs,KTestDatabase,KTestFormat),KErrNone);
+	TheDatabase.Close();
+	test.Next(_L("Open as shared"));
+	Connect();
+	test2 (TheDatabase.Open(TheDbs,KTestDatabase),KErrNone);
+	Execute(KCreateTable1);
+	test2 (TheTable.Open(TheDatabase,KTable1),KErrNone);
+	test2 (TheTable.ColCount(),4);
+	test2 (TheTable.ColType(1),EDbColInt32);
+	test2 (TheTable.ColType(2),EDbColText);
+	test2 (TheTable.ColType(3),EDbColLongText);
+	test2 (TheTable.ColType(4),EDbColLongBinary);
+	delete TheTable.ColSetL();
+	test.Next(_L("write table"));
+	WriteRecordsL(KRowCount);
+	test.Next(_L("Check table"));
+	TheTable.Reset();
+	test (TheTable.AtBeginning());
+	test (!TheTable.AtRow());
+	test (!TheTable.AtEnd());
+	test2 (TheTable.CountL(),KRowCount);
+	IterateL(TheTable.ENext);
+	test (!TheTable.AtBeginning());
+	test (!TheTable.AtRow());
+	test (TheTable.AtEnd());
+	test.Next(_L("Delete rows"));
+	test2 (DeleteL(),KRowCount);
+	TheTable.Close();
+	test.Next(_L("Drop table"));
+	Execute(KDropTable1);
+	TheDatabase.Close();
+	Disconnect();
+	test.End();
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0608
+@SYMTestCaseDesc        Tests for database locking
+@SYMTestPriority        Medium
+@SYMTestActions         Tests for shared,exclusive locks on database
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void TestLocking()
+	{
+	TInt r;
+	RDbNamedDatabase db;
+	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0608 Open databases "));
+	Connect();
+	test2 (TheDatabase.Open(TheDbs,KTestDatabase),KErrNone);
+	test2 (db.Open(TheDbs,KTestDatabase,KTestFormat),KErrNone);
+	RDbNotifier ob;
+	test2 (ob.Open(TheDatabase),KErrNone);
+//
+	test.Next(_L("Shared locks"));
+	TRequestStatus stat;
+	ob.NotifyUnlock(stat);
+	test2 (TheDatabase.Begin(),KErrNone);
+	test2 (db.Begin(),KErrNone);
+	test2 (TheDatabase.Commit(),KErrNone);
+	User::After(1);
+	test2 (stat.Int(),KRequestPending);		// should not report yet
+	test2 (db.Commit(),KErrNone);
+	User::WaitForRequest(stat);
+	test2 (stat.Int(),ob.EUnlock);
+//
+	test.Next(_L("Exclusive locks"));
+	ob.NotifyUnlock(stat);
+	test2 (TheDatabase.Begin(),KErrNone);
+	test2 (db.Begin(),KErrNone);
+	test2 (TheDatabase.Execute(KCreateTable1),KErrLocked);	// cannot acquire
+	test2 (db.Commit(),KErrNone);	// release lock
+	test2 (TheDatabase.Execute(KCreateTable1),KErrNone);	// upgrade to X-lock
+	test2 (db.Begin(),KErrLocked);	// cannot share
+	test2 (TheTable.Open(db,KTable1),KErrNone);
+	TRAP(r,TheTable.InsertL());		// cannot lock
+	test2 (r,KErrLocked);
+	TheTable.Close();
+	test2 (db.Execute(KDropTable1),KErrLocked);	// cannot lock
+	test2 (TheTable.Open(TheDatabase,KTable1),KErrNone);
+	TRAP(r,TheTable.InsertL());		// we own the lock
+	test2 (r,KErrNone);
+	TheTable.Cancel();
+	TheTable.Close();
+	test2 (TheDatabase.Execute(KDropTable1),KErrNone);
+	test2 (stat.Int(),KRequestPending);	// no NotifyUnlock yet
+	test2 (TheDatabase.Commit(),KErrNone);
+	User::WaitForRequest(stat);
+	test2 (stat.Int(),ob.ECommit);
+//
+	ob.Close();
+	db.Close();
+	TheDatabase.Close();
+	Disconnect();
+	test.End();
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0609
+@SYMTestCaseDesc        Tests for sharing a database
+@SYMTestPriority        Medium
+@SYMTestActions         Tests for opening a database more than once.
+                        Tests the integrity of the table data
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void TestShareL()
+	{
+	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0609 Open database "));
+	Connect();
+	TInt r=TheDatabase.Open(TheDbs,KTestDatabase);
+	test (r==KErrNone);
+	Execute(KCreateTable1);
+	test.Next(_L("Open it again"));
+	RDbNamedDatabase db;
+	test (db.Open(TheDbs,KTestDatabase,KTestFormat)==KErrNone);
+	test (TheTable.Open(db,KTable1)==KErrNone);
+	test2 (TheTable.ColCount(),4);
+	test2 (TheTable.ColType(1),EDbColInt32);
+	test2 (TheTable.ColType(2),EDbColText);
+	test2 (TheTable.ColType(3),EDbColLongText);
+	test2 (TheTable.ColType(4),EDbColLongBinary);
+	delete TheTable.ColSetL();
+	TheTable.Close();
+//
+	test.Next(_L("write table"));
+	test (TheTable.Open(TheDatabase,KTable1)==KErrNone);
+	WriteRecordsL(KRowCount);
+	TheTable.Close();
+	test.Next(_L("Check table"));
+	TheDatabase.Close();
+	TheDatabase=db;
+	test (TheTable.Open(TheDatabase,KTable1)==KErrNone);
+	test (TheTable.AtBeginning());
+	test (!TheTable.AtRow());
+	test (!TheTable.AtEnd());
+	test (TheTable.CountL()==KRowCount);
+	IterateL(TheTable.ENext);
+	test (!TheTable.AtBeginning());
+	test (!TheTable.AtRow());
+	test (TheTable.AtEnd());
+	test.Next(_L("Delete rows"));
+	test (DeleteSQL()==KRowCount);
+	TheTable.Close();
+	test.Next(_L("Drop table"));
+	Execute(KDropTable1);
+	TheDatabase.Close();
+	Disconnect();
+	test.End();
+	}
+
+LOCAL_C void TestScenario1L()
+	{
+	test.Start(_L("Take stream-lock on client 2"));
+	test (TheView.FirstL());
+	TheView.GetL();
+	RDbColReadStream rcol;
+	rcol.OpenLC(TheView,3);
+	test2 (rcol.ReadUint16L(),0);
+	test.Next(_L("Take a [shared] transaction-lock on client 1"));
+	test2 (TheDatabase.Begin(),KErrNone);
+	test.Next(_L("Attempt a write-lock on client 1"));
+	TRAPD(r,TheTable.InsertL());
+	test2 (r,KErrLocked);
+	test2 (rcol.ReadUint16L(),1);
+	test.Next(_L("Release locks on client 1 and then 2"));
+	TheDatabase.Rollback();
+	CleanupStack::PopAndDestroy();	// rcol
+	test.End();
+	}
+
+LOCAL_C void TestScenario2L()
+	{
+	test.Start(_L("Take stream-lock on client 2"));
+	test (TheView.FirstL());
+	TheView.GetL();
+	RDbColReadStream rcol;
+	rcol.OpenLC(TheView,3);
+	test2 (rcol.ReadUint16L(),0);
+	test.Next(_L("Take a [shared] transaction-lock on client 1"));
+	test2 (TheDatabase.Begin(),KErrNone);
+	test.Next(_L("Attempt a write-lock on client 1"));
+	TRAPD(r,TheTable.InsertL());
+	test2 (r,KErrLocked);
+	test2 (rcol.ReadUint16L(),1);
+	test.Next(_L("Release client 2 stream-lock"));
+	CleanupStack::PopAndDestroy();	// rcol
+	test.Next(_L("Take write-lock on client 1"));
+	TheTable.InsertL();				// read-lock removed
+	test.Next(_L("release client 1 locks"));
+	TheTable.Cancel();
+	TheDatabase.Rollback();
+	test.End();
+	}
+
+LOCAL_C void TestScenario3L(RDbDatabase& aClient2)
+	{
+	test.Start(_L("Take transaction-lock on client 1"));
+	test2 (TheDatabase.Begin(),KErrNone);
+	test.Next(_L("Take stream-lock on client 2"));
+	test (TheView.FirstL());
+	TheView.GetL();
+	RDbColReadStream rcol;
+	rcol.OpenLC(TheView,3);
+	test2 (rcol.ReadUint16L(),0);
+	test.Next(_L("Release client 1 lock"));
+	TheDatabase.Rollback();
+	test.Next(_L("Take write-lock on client 2"));
+	RDbTable table2;			// need a second cursor (cannot do insert with open streams)
+	test2 (table2.Open(aClient2,KTable1,table2.EInsertOnly),KErrNone);
+	TRAPD(r,table2.InsertL());
+	test2 (r,KErrNone);
+	test.Next(_L("Release stream-lock"));
+	CleanupStack::PopAndDestroy();
+	test.Next(_L("Release write-lock"));
+	table2.PutL();
+	table2.Close();
+	test.Next(_L("check the system is unlocked"));
+	test2 (TheDatabase.Begin(),KErrNone);
+	test2 (TheDatabase.Commit(),KErrNone);
+	test.End();
+	}
+
+LOCAL_C void TestScenario4L()
+	{
+	test.Start(_L("Take transaction-lock on client 1"));
+	test2 (TheDatabase.Begin(),KErrNone);
+	test.Next(_L("Take stream-lock on client 1"));
+	test (TheTable.FirstL());
+	TheTable.GetL();
+	RDbColReadStream rcol;
+	rcol.OpenLC(TheTable,3);
+	test2 (rcol.ReadUint16L(),0);
+	test.Next(_L("Take write-lock on client 1"));
+	RDbTable table2;			// need a second cursor (cannot do insert with open streams)
+	test2 (table2.Open(TheDatabase,KTable1,table2.EInsertOnly),KErrNone);
+	TRAPD(r,table2.InsertL());
+	test2 (r,KErrNone);
+	test.Next(_L("Release write-lock"));
+	table2.PutL();
+	table2.Close();
+	test.Next(_L("Release stream-lock"));
+	CleanupStack::PopAndDestroy();
+	test.Next(_L("release transaction-lock"));
+	test2 (TheDatabase.Commit(),KErrNone);
+	test.End();
+	}
+
+LOCAL_C void TestScenario5L()
+	{
+	test.Start(_L("Begin compaction on client 1"));
+	RDbIncremental inc;
+	TInt s;
+	test2 (inc.Compact(TheDatabase,s),KErrNone);
+	test.Next(_L("Attempt a stream-lock on client 2"));
+	test (TheView.FirstL());
+	TheView.GetL();
+	RDbColReadStream rcol;
+	TRAPD(r,rcol.OpenL(TheView,3));
+	test (r==KErrLocked);
+	test.Next(_L("Attempt a stream-lock on client 1"));
+	TRAP(r,rcol.OpenL(TheTable,3));
+	test (r==KErrAccessDenied);
+	test.Next(_L("Release compaction lock"));
+	inc.Close();
+	test.End();
+	}
+
+LOCAL_C void TestScenario6L()
+	{
+	test.Start(_L("Begin compaction on client 1 - open and read columns"));
+	TheTable.Close();
+
+	RDbIncremental inc;
+	TInt s;
+	test2 (inc.Compact(TheDatabase,s),KErrNone);
+
+	test.Next(_L("Attempt to open a table on client 1"));
+	TInt r=TheTable.Open(TheDatabase,KTable1);
+	test (r==KErrNone);
+
+	//read short column data
+	TheTable.FirstL();
+	TheTable.GetL();
+	TheTable.ColInt32(1);
+
+	// We cant write to tables
+	TRAP(r,TheTable.InsertL());
+	test (r==KErrAccessDenied);
+
+	RDbColReadStream rcol;
+	// We can't read long columns
+	TheTable.FirstL();
+	TheTable.GetL();
+	TRAP(r, rcol.OpenL(TheTable,3));
+	test2 (r,KErrAccessDenied);
+
+	// can read other columns
+	TRAP(r, rcol.OpenL(TheTable,4));
+	test2 (r,KErrNone);
+	rcol.Close();
+
+	test.Next(_L("Release compaction lock"));
+	inc.Close();
+	test.End();
+	}
+
+LOCAL_C void TestScenario7L()
+	{
+	test.Start(_L("Open tables on client 1 - Begin compaction on client 1"));
+
+	TheTable.Close();
+	test.Next(_L("Attempt to open a table on client 1"));
+	TInt r=TheTable.Open(TheDatabase,KTable1);
+	test (r==KErrNone);
+
+	test.Next(_L("Begin compaction on client 1"));
+	RDbIncremental inc;
+	TInt s;
+	test2 (inc.Compact(TheDatabase,s),KErrNone);
+
+	//read short column data
+	TheTable.FirstL();
+	TheTable.GetL();
+	TheTable.ColInt32(1);
+
+	// We cant write to tables
+	TRAP(r,TheTable.InsertL());
+	test (r==KErrAccessDenied);
+
+	RDbColReadStream rcol;
+	// cant read 4K text
+	TheTable.FirstL();
+	TheTable.GetL();
+	TRAP(r, rcol.OpenL(TheTable,3));
+	test2 (r,KErrAccessDenied);
+
+	// can read 1K blob
+	TRAP(r, rcol.OpenL(TheTable,4));
+	test2 (r,KErrNone);
+	rcol.Close();
+
+	test.Next(_L("Release compaction lock"));
+	inc.Close();
+	test.End();
+	}
+
+LOCAL_C void TestScenario8L()
+	{
+	test.Start(_L("Take update-lock on client 1"));
+	test2 (TheDatabase.Begin(),KErrNone);
+	TheTable.InsertL();
+	test.Next(_L("Read blob without locking on client 2"));
+	test (TheView.FirstL());
+	TheView.GetL();
+	RDbColReadStream rcol;
+	rcol.OpenLC(TheView,4);			// 1K blob
+	test2 (rcol.ReadInt32L(),0);
+	CleanupStack::PopAndDestroy();
+	TRAPD(r,rcol.OpenL(TheView,3));			// 4K text blob
+	test2 (r,KErrLocked);
+	test.Next(_L("Release client 1 lock"));
+	TheTable.Cancel();
+	TheDatabase.Rollback();
+	test.End();
+	}
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0610
+@SYMTestCaseDesc        Tests for a defect on database
+@SYMTestPriority        Medium
+@SYMTestActions         Tests for database connection
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void TestDefectL()
+	{
+	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0610 Build test database "));
+	Connect();
+	TInt r=TheDatabase.Open(TheDbs,KTestDatabase);
+	test (r==KErrNone);
+	Execute(KCreateTable1);
+	test2 (TheTable.Open(TheDatabase,KTable1),KErrNone);
+	TheTable.InsertL();
+	RDbColWriteStream wcol;
+	wcol.OpenLC(TheTable,3);
+	TInt ii;
+	for (ii=0;ii<2048;++ii)
+		wcol.WriteUint16L(ii);
+	wcol.CommitL();
+	CleanupStack::PopAndDestroy();
+	wcol.OpenLC(TheTable,4);
+	for (ii=0;ii<256;++ii)
+		wcol.WriteInt32L(ii);
+	wcol.CommitL();
+	CleanupStack::PopAndDestroy();
+	TheTable.PutL();
+//
+	test.Next(_L("open client 2 connection"));
+	RDbNamedDatabase db;
+	test2 (db.Open(TheDbs,KTestDatabase,KTestFormat),KErrNone);
+	test2 (TheView.Prepare(db,_L("select * from Table1")),KErrNone);
+	test2 (TheView.EvaluateAll(),KErrNone);
+//
+	test.Next(_L("Scenario 1"));
+	TestScenario1L();
+//
+	test.Next(_L("Scenario 2"));
+	TestScenario2L();
+//
+	test.Next(_L("Scenario 3"));
+	TestScenario3L(db);
+//
+	test.Next(_L("Scenario 4"));
+	TestScenario4L();
+//
+	test.Next(_L("Scenario 5"));
+	TestScenario5L();
+//
+	test.Next(_L("Scenario 6"));
+	TestScenario6L();
+//
+	test.Next(_L("Scenario 7"));
+	TestScenario7L();
+//
+	test.Next(_L("Scenario 8"));
+	TestScenario8L();
+//
+	
+	test.Next(_L("tidy up"));
+	test2 (TheDatabase.Begin(),KErrNone);
+	TheView.Close();
+	TheTable.Close();
+	db.Close();
+	Execute(KDropTable1);
+	test2 (TheDatabase.Commit(),KErrNone);
+	TheDatabase.Close();
+	Disconnect();
+	test.End();
+	}
+
+/**
+@SYMTestCaseID          PDS-DBMS-CT-4002
+@SYMTestCaseDesc	    Testing RDbIncremental API
+@SYMTestPriority 	    High
+@SYMTestActions  	    Executing SQL using RDbIncremental, Altering tables, creating and droping indexes
+@SYMTestExpectedResults After execution Table should exist in DB, after altering, table colums should change,
+						creation of index should create index column in table, dropping index should remove
+						it from table
+@SYMDEF                 DEF135710
+*/
+LOCAL_C void TestRDbIncrementalAPIL()
+	{
+	test.Start(_L(" @SYMTestCaseID:PDS-DBMS-CT-4002 Testing RDbIncremental API"));
+	
+	Connect();
+	TInt err = TheDatabase.Open(TheDbs,KTestDatabase);
+	test2(err, KErrNone);
+	
+	test.Next(_L("RDbIncremental API"));
+	RDbIncremental inc;
+	TInt step;
+	
+	test2(TheDatabase.Begin(), KErrNone);
+	err = inc.Execute(TheDatabase, KCreateTable2, step);
+	test2(err, KErrNone);	
+	while(step > 0)
+		{
+		err = inc.Next(step);
+		test2(err, KErrNone);
+		}
+	inc.Close();
+	
+	test.Next(_L("AlterTable"));
+	CDbColSet* colSet = CDbColSet::NewLC();
+	colSet->AddL(TDbCol(_L("Id2"), EDbColUint32));
+	colSet->AddL(TDbCol(_L("Memo2"), EDbColText));
+	test2(colSet->Count(), 2);
+	err = inc.AlterTable(TheDatabase, KTable2, *colSet, step);
+	test2(err, KErrNone);
+	while(step > 0)
+		{
+		err = inc.Next(step);
+		test2(err, KErrNone);
+		}
+	inc.Close();
+	err = TheDatabase.Commit();
+	test2(err, KErrNone);
+	
+	test.Next(_L("CreateIndex"));
+	TDbKeyCol kcol(_L("Id2"), TDbKeyCol::EAsc);
+	CDbKey* key = CDbKey::NewLC();
+	test2(TheDatabase.Begin(), KErrNone);
+	key->AddL(kcol);
+	err = inc.CreateIndex(TheDatabase, _L("Id2"), KTable2, *key, step);
+	test2(err, KErrNone);
+	while(step > 0)
+		{
+		err = inc.Next(step);
+		test2(err, KErrNone);
+		}
+	inc.Close();
+	
+	test.Next(_L("DropIndex"));
+	err = inc.DropIndex(TheDatabase, _L("Id2"), KTable2, step);
+	test2(err, KErrNone);
+	while(step > 0)
+		{
+		err = inc.Next(step);
+		test2(err, KErrNone);
+		} 
+	inc.Close();
+	err = inc.Execute(TheDatabase, KDropTable2, step);
+	test2(err, KErrNone);
+	while(step > 0)
+		{
+		err = inc.Next(step);
+		test2(err, KErrNone);
+		}
+	err = TheDatabase.Commit();
+	test2(err, KErrNone);
+	inc.Close();
+	
+	CleanupStack::PopAndDestroy(2);
+	
+	TheDatabase.Close();
+	Disconnect();
+	test.End();
+	}
+
+/**
+@SYMTestCaseID          PDS-DBMS-CT-4003
+@SYMTestCaseDesc	    Testing RDbUpdate API
+@SYMTestPriority 	    High
+@SYMTestActions  	    Executing DML command using RDbUpdate, checking if rowCount working properly
+@SYMTestExpectedResults After DML execution, rowCount should return proper number of afected rows. 
+@SYMDEF                 DEF135710
+*/
+LOCAL_C void TestRDbUpdate()
+{
+	test.Start(_L(" @SYMTestCaseID:PDS-DBMS-CT-4003 Testing RDbUpdate API"));
+	_LIT(DMLinsert, "INSERT INTO Table2 VALUES (2,'Mietek', 'Mietek ma kota')");
+	
+	Connect();
+	TInt err = TheDatabase.Open(TheDbs,KTestDatabase);
+	test2(err, KErrNone);
+	
+	err = TheDatabase.Begin();
+	test2(err, KErrNone);
+	
+	err = TheDatabase.Execute(KCreateTable2, EDbCompareNormal);
+	test(err >= KErrNone);
+	
+	RDbUpdate update;
+	err = update.Execute(TheDatabase, DMLinsert, EDbCompareNormal );
+	if(err != KErrNone)
+		RDebug::Printf("Error on Execute %d",err);
+	test2(err, KErrNone);	
+	
+	TInt rows = update.RowCount();
+	RDebug::Printf("Afected rows %d",rows);
+	test2(rows, 1);	
+	update.Close();
+	
+	err = TheDatabase.Commit();
+	test2(err, KErrNone);
+	
+	TheDatabase.Close();
+	Disconnect();
+	test.End();
+}
+
+/**
+@SYMTestCaseID          PDS-DBMS-CT-4004 
+@SYMTestCaseDesc	    Testing RDbRow API
+@SYMTestPriority 	    High
+@SYMTestActions  	    Test for construction functions for RDbRow
+@SYMTestExpectedResults After Creation/Opening row should be a valid object.
+@SYMDEF                 DEF135710
+*/
+LOCAL_C void TestRDbRowL()
+{
+	test.Start(_L(" @SYMTestCaseID:PDS-DBMS-CT-4004 Testing RDbRow API"));
+	const TInt KRowSize = 300;
+	const TInt KRealRowSize = 512;
+
+	RDbRow row;
+	row.CreateL(KRowSize);
+	RDebug::Printf("Rows %d %d",row.Size(), row.MaxSize() );
+	test2(row.MaxSize(), KRealRowSize);
+	TAny* rptr = row.First();
+	
+	RDbRow row2;
+	row2.Open(rptr, KRowSize, 2*KRowSize);
+	RDebug::Printf("Row2s %d %d", KRowSize, row2.MaxSize());
+	test2(row2.Size(), KRowSize);
+	test2(row2.MaxSize(), 2*KRowSize);
+	
+	row.Close();
+	row2.Close();
+	test.End();
+}
+/*
+ * Helper function for SYSLIB-DBMS-CT-4005 Testing TTextOps API
+ */
+LOCAL_C TInt HelperCompareForTestTTextOps(const TText8*,TInt,const TText8*,TInt)
+	{
+	return KReturnValueForCompare;
+	}
+/*
+ * Helper function for SYSLIB-DBMS-CT-4005 Testing TTextOps API
+ */
+LOCAL_C TInt HelperFindForTestTTextOps(const TDesC8&,const TText8*,TInt)
+	{
+	return KReturnValueForFind;
+	}
+/**
+@SYMTestCaseID          PDS-DBMS-CT-4005
+@SYMTestCaseDesc	    Testing TTextOps API
+@SYMTestPriority 	    High
+@SYMTestActions  	    Test for Compare and Find functions for TTextOps
+@SYMTestExpectedResults Test if those functions really calling proper targets.
+@SYMDEF                 DEF135710
+*/
+LOCAL_C void TestTTextOps()
+{
+	test.Start(_L(" @SYMTestCaseID:PDS-DBMS-CT-4005 Testing TTextOps API"));
+	TTextOps text;
+	
+	text.iCompare8 = HelperCompareForTestTTextOps;
+	text.iFind8 = HelperFindForTestTTextOps;
+	TInt ret = text.Compare(_L8("Ala ma kota"), _L8("Ala ma konia"));
+	test2(ret, KReturnValueForCompare);
+	ret = text.Find(_L8("Ala ma kota"), _L8("ma ko"));
+	test2(ret, KReturnValueForFind);
+	
+	test.End();
+}
+
+#if defined __WINS__ ||	defined __WINSCW__
+
+LOCAL_C TInt ExecuteRemoteL(const TDesC& aCommand, const TDesC& aCommandLineArg)
+	{
+	RProcess process;
+	User::LeaveIfError(process.Create(aCommand, aCommandLineArg));
+	
+	TRequestStatus status;
+	process.Logon(status);
+	process.Resume();
+
+	User::WaitForRequest(status);
+	TInt exitReason = process.ExitReason();
+	
+	process.Close();
+	User::LeaveIfError(exitReason);
+	
+	return exitReason;
+	}
+
+#endif //defined __WINS__ ||	defined __WINSCW__
+
+/**
+@SYMTestCaseID          PDS-DBMS-CT-4007
+@SYMTestCaseDesc	    Testing SPConv - This test case uses the Edbsconv tool 
+						so therefore only runs on WINSCW builds
+@SYMTestPriority 	    High
+@SYMTestActions  	    Launch the external tool to generate SPD files
+@SYMTestExpectedResults Should produce SPD files and report no errors
+@SYMDEF                 DEF135710
+*/
+LOCAL_C void TestSPConvL()
+	{
+	test.Start(_L(" @SYMTestCaseID:PDS-DBMS-CT-4007 Testing SPConv"));
+	
+#if defined __WINS__ ||	defined __WINSCW__
+	
+	_LIT(KRomTxtFile1, "z:\\test\\11335577.txt");
+	_LIT(KRomTxtFile2, "z:\\test\\11335578.txt");
+	_LIT(KRomTxtFile3, "z:\\test\\11335579.txt");
+	_LIT(KRomTxtFile4, "z:\\test\\1133557A.txt");
+	_LIT(KCommand,"Edbspconv");
+	_LIT(KCommandParameter, " /f=%S /b=%S /s");
+	
+	TBuf<200> commandParameter;
+	
+	test.Next(_L("Create SPD File from \"11335577.txt\""));
+	commandParameter.Format(KCommandParameter, &KRomTxtFile1, &KTestSpdFile1);
+	ExecuteRemoteL(KCommand, commandParameter);
+		
+	test.Next(_L("Create SPD File from \"11335578.txt\""));
+	commandParameter.Format(KCommandParameter, &KRomTxtFile2, &KTestSpdFile2);
+	ExecuteRemoteL(KCommand, commandParameter);
+	
+	test.Next(_L("Create SPD File from \"11335579.txt\""));
+	commandParameter.Format(KCommandParameter, &KRomTxtFile3, &KTestSpdFile3);
+	ExecuteRemoteL(KCommand, commandParameter);
+	
+	test.Next(_L("Create SPD File from \"1133557A.txt\""));
+	commandParameter.Format(KCommandParameter, &KRomTxtFile4, &KTestSpdFile4);
+	ExecuteRemoteL(KCommand, commandParameter);
+	
+#else
+	RDebug::Print(_L("Testing SPConv - This test case cannot run on hardware"));
+#endif	
+	
+	test.Next(_L("End"));
+	test.End();
+	}
+
+
+/**
+@SYMTestCaseID          SYSLIB-DBMS-CT-0611
+@SYMTestCaseDesc        Tests the behaviour of observers
+@SYMTestPriority        Medium
+@SYMTestActions         Tests for DDL,DML
+@SYMTestExpectedResults Test must not fail
+@SYMREQ                 REQ0000
+*/
+LOCAL_C void TestObserverL()
+	{
+	test.Start(_L(" @SYMTestCaseID:SYSLIB-DBMS-CT-0611 Single connection/observer "));
+	Connect();
+	TInt r=TheDatabase.Open(TheDbs,KTestDatabase);
+	test (r==KErrNone);
+	RDbNotifier ob;
+	r=ob.Open(TheDatabase);
+	test (r==KErrNone);
+//
+	test.Next(_L("Cancel"));
+	TRequestStatus stat;
+	ob.NotifyUnlock(stat);
+	test (stat==KRequestPending);
+	ob.Cancel();
+	User::WaitForRequest(stat);
+	test (stat==KErrCancel);
+//
+	test.Next(_L("Close"));
+	ob.NotifyUnlock(stat);
+	test (stat==KRequestPending);
+	ob.Close();
+	User::WaitForRequest(stat);
+	test (stat==KErrCancel);
+//
+	test.Next(_L("DDL"));
+	r=ob.Open(TheDatabase);
+	test (r==KErrNone);
+	ob.NotifyUnlock(stat);
+	test (stat==KRequestPending);
+	Execute(KCreateTable1);
+	User::WaitForRequest(stat);
+	test (stat==ob.ECommit);
+//
+	test.Next(_L("DML"));
+	ob.NotifyUnlock(stat);
+	test (stat==KRequestPending);
+	r=TheTable.Open(TheDatabase,KTable1);
+	test (r==KErrNone);
+	WriteRecordsL(50);
+	User::WaitForRequest(stat);
+	test (stat==ob.ECommit);
+//
+	test.Next(_L("Locked read"));
+	ob.NotifyUnlock(stat);
+	TheDatabase.Begin();
+	test (stat==KRequestPending);
+	TheDatabase.Commit();
+	User::WaitForRequest(stat);
+	test (stat==ob.EUnlock);
+//
+	test.Next(_L("Database closed"));
+	ob.NotifyUnlock(stat);
+	TheTable.Close();
+	TheDatabase.Close();
+	User::WaitForRequest(stat);
+	test (stat==ob.EClose);
+	ob.NotifyUnlock(stat);
+	User::WaitForRequest(stat);
+	test (stat==ob.EClose);
+//
+	test.Next(_L("Re-open database"));
+	r=TheDatabase.Open(TheDbs,KTestDatabase);
+	test (r==KErrNone);
+	ob.NotifyUnlock(stat);
+	User::WaitForRequest(stat);
+	test (stat==ob.EClose);
+	ob.Close();
+//
+	test.Next(_L("Multiple connections and observers"));
+	r=ob.Open(TheDatabase);
+	test (r==KErrNone);
+	RDbNamedDatabase db2;
+	r=db2.Open(TheDbs,KTestDatabase);
+	test (r==KErrNone);
+	RDbNotifier ob2;
+	r=ob2.Open(db2);
+	test (r==KErrNone);
+//
+	test.Next(_L("Cancel"));
+	ob.NotifyUnlock(stat);
+	TRequestStatus stat2;
+	ob2.NotifyUnlock(stat2);
+	test (stat==KRequestPending);
+	ob.Cancel();
+	User::WaitForRequest(stat);
+	test (stat==KErrCancel);
+	test (stat2==KRequestPending);
+	ob2.Cancel();
+	User::WaitForRequest(stat2);
+	test (stat2==KErrCancel);
+//
+	test.Next(_L("Close"));
+	ob.NotifyUnlock(stat);
+	ob2.NotifyUnlock(stat2);
+	test (stat2==KRequestPending);
+	ob2.Close();
+	User::WaitForRequest(stat2);
+	test (stat2==KErrCancel);
+	test (stat==KRequestPending);
+	ob.Close();
+	User::WaitForRequest(stat);
+	test (stat==KErrCancel);
+//
+	test.Next(_L("NotifyChange"));
+	r=ob.Open(TheDatabase);
+	test (r==KErrNone);
+	r=ob2.Open(db2);
+	test (r==KErrNone);
+	ob.NotifyUnlock(stat);
+	ob2.NotifyChange(stat2);
+	TheDatabase.Begin();
+	r=TheDatabase.Commit();
+	test (r==KErrNone);
+	User::WaitForRequest(stat);
+	test (stat==ob.EUnlock);
+	test (stat2==KRequestPending);
+	ob.NotifyUnlock(stat);
+	db2.Begin();
+	r=db2.Commit();
+	test (r==KErrNone);
+	User::WaitForRequest(stat);
+	test (stat==ob.EUnlock);
+	test (stat2==KRequestPending);
+	Execute(KDropTable1);
+	User::WaitForRequest(stat2);
+	test (stat2==ob.ECommit);
+//
+	test.Next(_L("missed event"));
+	ob.NotifyUnlock(stat);
+	User::WaitForRequest(stat);
+	test (stat==ob.ECommit);
+//
+	test.Next(_L("database close"));
+	ob.NotifyUnlock(stat);
+	test (stat==KRequestPending);
+	ob2.NotifyUnlock(stat2);
+	test (stat2==KRequestPending);
+	TheDatabase.Close();
+	User::After(0x20000);	// ~.1s
+	test (stat==KRequestPending);
+	test (stat2==KRequestPending);
+	db2.Close();
+	User::WaitForRequest(stat);
+	test (stat==ob.EClose);
+	User::WaitForRequest(stat2);
+	test (stat2==ob.EClose);
+	ob.NotifyUnlock(stat);
+	User::WaitForRequest(stat);
+	test (stat==ob.EClose);
+	ob.Cancel();
+	ob.Close();
+	ob2.NotifyUnlock(stat2);
+	User::WaitForRequest(stat2);
+	test (stat2==ob.EClose);
+	ob2.Cancel();
+	ob2.Close();
+//
+	Disconnect();
+	test.End();
+	}
+
+LOCAL_C void setupTestDirectory()
+//
+// Prepare the test directory.
+//
+    {
+	TInt r=TheFs.Connect();
+	test(r==KErrNone);
+//
+	r=TheFs.MkDir(KTestDatabase);
+	test(r==KErrNone || r==KErrAlreadyExists);
+	}
+
+LOCAL_C void setupCleanup()
+//
+// Initialise the cleanup stack.
+//
+    {
+	TheTrapCleanup=CTrapCleanup::New();
+	test(TheTrapCleanup!=NULL);
+	TRAPD(r,\
+		{\
+		for (TInt i=KTestCleanupStack;i>0;i--)\
+			CleanupStack::PushL((TAny*)0);\
+		CleanupStack::Pop(KTestCleanupStack);\
+		});
+	test(r==KErrNone);
+	}
+
+void DoTests()
+	{
+	TVersionName n=RDbs::Version().Name();
+	test.Printf(_L("DBMS server v%S\n"),&n);
+	TInt r;
+	test.Start(_L("Connection"));
+	TestConnect();
+	
+	test.Next(_L("Open Database"));
+	TRAP(r,TestOpenL());
+	test2 (r,KErrNone);
+	
+	test.Next(_L("test defect"));
+	TRAP(r,TestDefectL());
+	test2 (r,KErrNone);
+	
+	test.Next(_L("Share Database"));
+	TRAP(r,TestShareL());
+	test2 (r,KErrNone);
+	
+	test.Next(_L("Locking"));
+	TRAP(r,TestLocking());
+	test2 (r,KErrNone);
+	
+	test.Next(_L("Observers"));
+	TRAP(r,TestObserverL());
+	test2 (r,KErrNone);
+	
+	test.Next(_L("Benchmarks"));
+	TRAP(r,TestBenchL());
+	test2 (r,KErrNone);
+	
+	test.Next(_L("RDbIncremental"));
+	TRAP(r, TestRDbIncrementalAPIL() );
+	test2 (r,KErrNone);
+	
+	test.Next(_L("RDbUpdate"));
+	TestRDbUpdate();
+
+	test.Next(_L("RDbRow"));
+	TRAP(r, TestRDbRowL() );
+	test2 (r,KErrNone);
+	
+	test.Next(_L("TTextOpsL"));
+	TestTTextOps();
+	
+	test.Next(_L("TestSPConvL"));
+	TRAP(r, TestSPConvL() );
+	test2 (r, KErrNone);
+	
+	test.Next(_L("Waiting for server exit"));
+	}
+
+
+GLDEF_C TInt E32Main()
+//
+// Test streaming conversions.
+//
+    {
+	__UHEAP_MARK;
+	
+	test.Title();
+	setupTestDirectory();
+	DeleteTestFiles();
+	setupCleanup();
+	DoTests();
+	delete TheTrapCleanup;
+	DeleteTestFiles();
+	
+	test.End();
+	TheFs.Close();
+	test.Close();
+	__UHEAP_MARKEND;
+	return 0;
+    }