messagingfw/msgtest/testutils/server/src/Msgservertestutils.cpp
changeset 0 8e480a14352b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/msgtest/testutils/server/src/Msgservertestutils.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,631 @@
+// Copyright (c) 1999-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:
+// msgservertestutils.cpp
+//
+
+#include "msgservertestutils.h"
+
+#include <e32test.h>
+#include <f32fsys.h>
+#include <s32file.h>
+#include <e32uid.h>
+#include <txtrich.h>
+#include <txtfmlyr.h>
+#include <msvids.h>
+#include <msvuids.h>
+#include <msvruids.h>
+#include <e32std.h>
+#include <mtclbase.h>
+#include <mtclreg.h>
+#include <msvapi.h>
+#include <mtmuids.h>
+#include <smuthdr.h>
+#include <miutset.h>
+#include <sqldb.h>
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS  
+#include "msvconsts.h"
+#endif
+
+_LIT(KMsvServerPattern, "!MsvServer*");
+_LIT(KMsgServerTestUtilsPanic,"MSGS-TESTS");
+#ifdef SYMBIAN_MESSAGESTORE_UNIT_TESTCODE
+_LIT(KDbFileName, "\\messaging.db");
+#else
+_LIT(KDbFileName, "[1000484B]messaging.db");
+#endif
+
+
+class CDummyObserver : public CBase, public MMsvSessionObserver
+	{
+public:
+	void HandleSessionEventL(TMsvSessionEvent, TAny*, TAny*, TAny*) {};
+	};
+
+
+EXPORT_C CMsgServerTestUtils* CMsgServerTestUtils::NewL(RTest& aRTest)
+	{
+	CMsgServerTestUtils* self = NewLC(aRTest);
+	CleanupStack::Pop();
+	return self;
+	}
+
+EXPORT_C CMsgServerTestUtils* CMsgServerTestUtils::NewLC(RTest& aRTest)
+	{
+	CMsgServerTestUtils* self = new (ELeave) CMsgServerTestUtils(aRTest);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+
+
+CMsgServerTestUtils::CMsgServerTestUtils(RTest& aRTest)
+: CTestUtils(aRTest)
+	{
+	iTestNum=0;
+	}
+
+CMsgServerTestUtils::~CMsgServerTestUtils()
+	{
+	delete CActiveScheduler::Current();
+	}
+
+
+void CMsgServerTestUtils::ConstructL()
+	{
+	CTestUtils::ConstructL();
+	}
+
+
+void CMsgServerTestUtils::Panic(TInt aPanic)
+	{
+	User::Panic(KMsgServerTestUtilsPanic, aPanic);
+	}
+
+
+
+EXPORT_C void CMsgServerTestUtils::SetDebugL(TBool aDebug)
+	{
+	TMsvConfig config;
+	GetConfigL(config);
+	config.iDebug = aDebug;
+	SetConfigL(config);
+	}
+
+EXPORT_C void CMsgServerTestUtils::GetConfigL(TMsvConfig& aConfig)
+	{
+	// try to open system ini
+	TUint unused;        
+	TChar iDriveChar=FileSession().GetSystemDriveChar();
+ 	TBuf<2> systemDrive;
+ 	systemDrive.Append(iDriveChar);
+ 	systemDrive.Append(KDriveDelimiter);
+ 	TPath pathName(systemDrive);
+	pathName.Append(KServerINIFile);  
+ 	if(FileSession().Att(pathName,unused)==KErrNone)
+		{
+		CDictionaryFileStore *store = CDictionaryFileStore::OpenLC(FileSession(),pathName,KNullUid);
+		// get configuration from system ini
+		if (store->IsPresentL(KUidMsvMessageDriveStream))
+			{
+			RDictionaryReadStream readStream;
+			readStream.OpenLC(*store, KUidMsvMessageDriveStream);
+			TInt version = readStream.ReadInt8L();
+			iRTest(version <= KMsvMessageDriveStreamVersionNumber);
+
+			TBuf<2> drive;
+			readStream >> drive;
+			aConfig.iDrive = drive;
+
+			aConfig.iUniqueID = 0;
+			aConfig.iDebug = EFalse;
+
+			// The drive Id didn't exist in earlier versions
+			if (version > 1)
+				aConfig.iUniqueID = readStream.ReadUint32L();
+
+			// This debug frig wasn't in earlier versions
+			if (version > 2)
+				aConfig.iDebug = readStream.ReadInt8L();
+
+			CleanupStack::PopAndDestroy(); // readStream
+			}
+
+		CleanupStack::PopAndDestroy(); // store
+                }
+	}
+
+EXPORT_C void CMsgServerTestUtils::SetConfigL(TMsvConfig& aConfig)
+	{
+	TChar iDriveChar=FileSession().GetSystemDriveChar();
+ 	TBuf<2> systemDrive;
+ 	systemDrive.Append(iDriveChar);
+ 	systemDrive.Append(KDriveDelimiter);
+    TPath pathName(systemDrive);
+ 	pathName.Append(KServerINIFile);  
+ 	CDictionaryFileStore *store = CDictionaryFileStore::OpenLC(FileSession(),pathName,KNullUid);
+	RDictionaryWriteStream stream;
+	stream.AssignLC(*store, KUidMsvMessageDriveStream);
+
+	stream.WriteUint8L(KMsvMessageDriveStreamVersionNumber); // version number
+	stream << aConfig.iDrive.Name();
+	stream.WriteUint32L(aConfig.iUniqueID);
+	stream.WriteInt8L(aConfig.iDebug);
+
+	stream.CommitL();
+	store->CommitL();
+	CleanupStack::PopAndDestroy(2); // stream, store
+	}
+
+
+
+EXPORT_C void CMsgServerTestUtils::SetupL()
+	{
+	CActiveScheduler::Install(new(ELeave)CTestScheduler);
+	iRTest.Printf(_L("Cleaning Message Folder\n"));
+	CleanMessageFolderL();
+	SetDriveL(EDriveC);
+	SetDebugL(ETrue);
+
+	// Try and find the removable drive
+	for (iRemovableDrive = EDriveY; iRemovableDrive > EDriveD; iRemovableDrive = TInt(iRemovableDrive) - 1)
+		{
+		TVolumeInfo info;
+		if (FileSession().Volume(info, TInt(iRemovableDrive)) == KErrNone)
+			break;
+		}
+	}
+
+
+EXPORT_C void CMsgServerTestUtils::SetDriveL(TInt aDrive, TBool aStoreId)
+	{
+	TMsvConfig config;
+	GetConfigL(config);
+
+	config.iDrive = aDrive;
+
+	if (aStoreId)
+		config.iUniqueID = (TUint)-1;
+	else
+		config.iUniqueID = 0;
+
+	SetConfigL(config);
+	}
+
+
+EXPORT_C void CMsgServerTestUtils::Close(TInt aRet)
+	{
+	if (!aRet)
+		TestHarnessCompleted();
+	else
+		TestHarnessFailed(aRet);
+	}
+
+
+EXPORT_C void CMsgServerTestUtils::CleanMessageFolderL(const TDesC& aDes)
+	{
+	CFileMan* fileMan = CFileMan::NewL(FileSession());
+	CleanupStack::PushL(fileMan);
+
+	TParse parse;
+	TFileName fileName((aDes.Length() == 0) ? KMsvDefaultFolder2 : aDes);
+	TMsvConfig config;
+
+	TChar driveChar=FileSession().GetSystemDriveChar();
+ 	TBuf<4> drive;
+ 	drive.Append(driveChar);
+ 	drive.Append(KDriveDelimiter);
+	config.iDrive=TDriveUnit(drive);
+	GetConfigL(config);
+	TDriveName name=config.iDrive.Name();
+	parse.Set(fileName, &name, NULL);
+
+	TInt error = fileMan->RmDir(parse.DriveAndPath());
+	CleanupStack::PopAndDestroy(); // fileMan
+
+	error = FileSession().RmDir(parse.DriveAndPath());
+	if (!(error == KErrNotFound || error == KErrNone || error==KErrPathNotFound))
+		{
+		TPtrC dir(parse.DriveAndPath());
+		iRTest.Printf(TRefByValue<const TDesC>(_L("Directory %S cannot be removed\n Exiting - press any key...\n")), &dir);
+		User::Leave(KErrNotReady);
+		}
+
+	//delete DB
+	TDriveUnit driveUnit(drive);
+ 	TPath pathName(driveUnit.Name());
+ 	pathName.Append(KDbFileName);
+ 	RSqlDatabase::Delete(pathName);
+	}
+
+
+EXPORT_C CMsvServer* CMsgServerTestUtils::CreateServerL(const TDesC& aIndexFile)
+	{	
+	TDesC dummy = aIndexFile; //dummy to avoid test build error when aIndexFile is not used inside
+	CMsvServer* server = CMsvServer::NewL();
+	CleanupStack::PushL(server);
+
+	CTestTimer* timer = CTestTimer::NewL();
+	timer->After(100000);
+	CActiveScheduler::Start();
+	delete timer;
+
+	CleanupStack::Pop(); // server
+	return server;
+	}
+
+
+EXPORT_C void CMsgServerTestUtils::FileExists(const TDesC& aDes)
+	{
+	TUint at;
+	iRTest(FileSession().Att(aDes, at)==KErrNone);
+	}
+
+EXPORT_C void CMsgServerTestUtils::FileMissing(const TDesC& aDes)
+	{
+	TUint at;
+	TInt error = FileSession().Att(aDes, at);
+	iRTest(error==KErrNotFound || error==KErrPathNotFound);
+	}
+
+
+EXPORT_C void CMsgServerTestUtils::CreateDataFilesL(const TDesC& aFilename, const TDesC& aMtmName, TUid aUid, const TDesC& aServerMtmFileName, const TDesC& aClientMtmFileName)
+	{
+	CMtmDllInfoArray* mtmdllinfoarray=new(ELeave) CMtmDllInfoArray();
+	CleanupStack::PushL(mtmdllinfoarray);
+
+	CMtmDllInfo* mtmdllinfo1=CMtmDllInfo::NewL(aMtmName, TUidType(KDynamicLibraryUid, KUidMtmServerComponent, TUid::Uid(KUidMtmDefaultSpecificVal)),aServerMtmFileName,1,TVersion(2,0,0));
+	mtmdllinfoarray->AddMtmDllInfoL(mtmdllinfo1);
+
+	CMtmDllInfo* mtmdllinfo2=CMtmDllInfo::NewL(aMtmName, TUidType(KDynamicLibraryUid, KUidMtmClientComponent, TUid::Uid(KUidMtmDefaultSpecificVal)),aClientMtmFileName,1,TVersion(2,0,0));
+	mtmdllinfoarray->AddMtmDllInfoL(mtmdllinfo2);
+
+	// Create an empty capability set for creating a new group data object
+	TCapabilitySet capSet;
+	capSet.SetEmpty();
+	CleanupStack::Pop(mtmdllinfoarray); // next line takes ownership
+	CMtmGroupData* mtmgroupdata=CMtmGroupData::NewL(aUid,aUid, mtmdllinfoarray, capSet);
+	CleanupStack::PushL(mtmgroupdata);
+
+	CFileStore* filestore = CPermanentFileStore::ReplaceLC(FileSession(), aFilename, EFileShareExclusive|EFileStream|EFileWrite);
+	TUidType uidtype(KPermanentFileStoreLayoutUid,KUidMsvDataComponent, aUid);
+	filestore->SetTypeL(uidtype);
+	RStoreWriteStream out;
+	TStreamId streamid=out.CreateLC(*filestore);							// Push to stack
+	mtmgroupdata->ExternalizeL(out);
+	out.CommitL();
+	CleanupStack::PopAndDestroy(); // out
+	filestore->SetRootL(streamid);
+	filestore->CommitL();
+	CleanupStack::PopAndDestroy(); // filestore
+	
+	CleanupStack::PopAndDestroy();  // mtmgroupdata
+	}
+
+EXPORT_C void CMsgServerTestUtils::InstallMtmL(const TDesC& aDataFile, const TDesC& aMtmName, TUid aId, const TDesC& aServerMtmFileName, const TDesC& aClientMtmFileName)
+	{
+	CDummyObserver* ob = new(ELeave)CDummyObserver;
+	CleanupStack::PushL(ob);
+
+	CMsvSession* session = CMsvSession::OpenSyncL(*ob);
+	CleanupStack::PushL(session);
+	
+	CreateDataFilesL(aDataFile, aMtmName, aId, aServerMtmFileName, aClientMtmFileName); 
+	session->InstallMtmGroup(aDataFile);
+
+	CleanupStack::PopAndDestroy(2); // session, ob
+	}
+
+EXPORT_C TBool CMsgServerTestUtils::WaitForKeyL(TTimeIntervalMicroSeconds32 aDelay, TKeyCode* aKeyCode)
+	{
+	iRTest(iRTest.Console() != NULL);
+
+	// Create timer
+	CTestTimer* timer = CTestTimer::NewL();
+	CleanupStack::PushL(timer);
+	timer->After(aDelay);
+
+	CTestActive* wait = new(ELeave)CTestActive;
+	CleanupStack::PushL(wait);
+	wait->StartL();
+
+	// Wait for key press
+	iRTest.Console()->Read(wait->iStatus);
+	CActiveScheduler::Start();
+
+	// If timer still active a key was pressed
+	TBool keyPressed = timer->IsActive();
+
+	if (keyPressed)
+		{
+		// Get the key pressed
+		if (aKeyCode)
+			*aKeyCode = iRTest.Console()->KeyCode();
+
+		// Cancel timer
+		timer->Cancel();
+		}
+	else
+		{
+		// Cancel wait for character
+		iRTest.Console()->ReadCancel();
+		User::WaitForRequest(wait->iStatus);
+		}
+
+	CleanupStack::PopAndDestroy(2); // wait, timer
+	return keyPressed;
+	}
+
+
+EXPORT_C void CMsgServerTestUtils::WaitForServerClose()
+	{
+	//Kill the message server if its running
+	TFindProcess findprocess(KMsvServerPattern);
+	TFullName name;
+	if(findprocess.Next(name)==KErrNone)
+		{
+		RProcess process;
+    	User::LeaveIfError(process.Open(findprocess));
+     	process.Kill(KErrCancel) ;
+		process.Close() ;
+		}
+		
+	FOREVER
+		{
+		TFullName name;
+		TFindProcess find(KMsvServerPattern);
+		if (find.Next(name) != KErrNone)
+			break;
+		User::After(100000);
+		}
+	}
+
+
+EXPORT_C void CMsgServerTestUtils::RemoveMailFolderL(TInt aDrive)
+	{
+	CFileMan* fileMan = CFileMan::NewL(FileSession());
+	CleanupStack::PushL(fileMan);
+
+	TDriveUnit drive(aDrive);
+	TPtrC ptr(drive.Name());
+
+	TParse parse;
+#ifdef __MESSAGING_API_V2
+	iRTest(parse.Set(ptr, &KMsvDefaultIndexFile2(), NULL) == KErrNone);
+#else
+	iRTest(parse.Set(ptr, &KMsvDefaultIndexFile(), NULL) == KErrNone);
+#endif
+
+	TInt error = fileMan->RmDir(parse.DriveAndPath());
+	iRTest(error == KErrNone || error == KErrPathNotFound);
+
+	CleanupStack::PopAndDestroy();
+	}
+
+EXPORT_C void CMsgServerTestUtils::RemoveIndexFile(TInt aDrive)
+	{
+	TDriveUnit drive(aDrive);
+	TPtrC ptr(drive.Name());
+
+	TParse parse;
+#ifdef __MESSAGING_API_V2
+	iRTest(parse.Set(ptr, &KMsvDefaultIndexFile2(), NULL) == KErrNone);
+#else
+	iRTest(parse.Set(ptr, &KMsvDefaultIndexFile(), NULL) == KErrNone);
+#endif
+
+	iRTest(FileSession().Delete(parse.FullName()) == KErrNone);
+	}
+
+EXPORT_C void CMsgServerTestUtils::CorruptIndexFileL(TInt aMode, const TDesC& aDes)
+	{
+	switch (aMode)
+		{
+		case 0: // uicode/narrow conflict
+			{
+#ifdef __MESSAGING_API_V2
+			FileSession().Delete((aDes.Length() == 0) ? KMsvDefaultIndexFile2 : aDes);
+			CPermanentFileStore* indexStore = CPermanentFileStore::CreateL(FileSession(), (aDes.Length() == 0) ? KMsvDefaultIndexFile2 : aDes, EFileShareExclusive|EFileWrite);
+#else
+			FileSession().Delete((aDes.Length() == 0) ? KMsvDefaultIndexFile : aDes);
+			CPermanentFileStore* indexStore = CPermanentFileStore::CreateL(FileSession(), (aDes.Length() == 0) ? KMsvDefaultIndexFile : aDes, EFileShareExclusive|EFileWrite);
+#endif
+			indexStore->SetTypeL(TUidType(KPermanentFileStoreLayoutUid, KNullUid)); // 2nd uid should be KUidMsvIndexFile
+			indexStore->CommitL();
+			delete indexStore;
+			break;
+			}
+		case 1: // empty index file
+			{
+#ifdef __MESSAGING_API_V2
+			FileSession().Delete((aDes.Length() == 0) ? KMsvDefaultIndexFile2 : aDes);
+			CPermanentFileStore* indexStore = CPermanentFileStore::CreateL(FileSession(), (aDes.Length() == 0) ? KMsvDefaultIndexFile2 : aDes, EFileShareExclusive|EFileWrite);
+#else
+			FileSession().Delete((aDes.Length() == 0) ? KMsvDefaultIndexFile : aDes);
+			CPermanentFileStore* indexStore = CPermanentFileStore::CreateL(FileSession(), (aDes.Length() == 0) ? KMsvDefaultIndexFile : aDes, EFileShareExclusive|EFileWrite);
+#endif
+			indexStore->SetTypeL(TUidType(KPermanentFileStoreLayoutUid, KUidMsvIndexFile)); // 2nd uid should be KUidMsvIndexFile
+			indexStore->CommitL();
+			delete indexStore;
+			break;
+			}
+		case 2: // missing index stream
+			{
+#ifdef __MESSAGING_API_V2
+			FileSession().Delete((aDes.Length() == 0) ? KMsvDefaultIndexFile2 : aDes);
+			CPermanentFileStore* indexStore = CPermanentFileStore::CreateL(FileSession(), (aDes.Length() == 0) ? KMsvDefaultIndexFile2 : aDes, EFileShareExclusive|EFileWrite);
+#else
+			FileSession().Delete((aDes.Length() == 0) ? KMsvDefaultIndexFile : aDes);
+			CPermanentFileStore* indexStore = CPermanentFileStore::CreateL(FileSession(), (aDes.Length() == 0) ? KMsvDefaultIndexFile : aDes, EFileShareExclusive|EFileWrite);
+#endif
+			indexStore->SetTypeL(TUidType(KPermanentFileStoreLayoutUid, KUidMsvIndexFile)); // 2nd uid should be KUidMsvIndexFile
+			//
+			RStoreWriteStream writeStream;
+			TStreamId rootIndexId = writeStream.CreateLC(*indexStore);
+			writeStream.WriteInt32L(TInt(rootIndexId.Value()+100));
+			writeStream.WriteInt32L(TInt(rootIndexId.Value()+101));
+			writeStream.CommitL();
+			CleanupStack::PopAndDestroy(); // writeStream
+			indexStore->SetRootL(rootIndexId);
+			//	
+			indexStore->CommitL();
+			delete indexStore;
+			break;
+			}
+		case 3: // missing entry stream
+			{
+#ifdef __MESSAGING_API_V2
+			FileSession().Delete((aDes.Length() == 0) ? KMsvDefaultIndexFile2 : aDes);
+			CPermanentFileStore* indexStore = CPermanentFileStore::CreateL(FileSession(), (aDes.Length() == 0) ? KMsvDefaultIndexFile2 : aDes, EFileShareExclusive|EFileWrite);
+#else
+			FileSession().Delete((aDes.Length() == 0) ? KMsvDefaultIndexFile : aDes);
+			CPermanentFileStore* indexStore = CPermanentFileStore::CreateL(FileSession(), (aDes.Length() == 0) ? KMsvDefaultIndexFile : aDes, EFileShareExclusive|EFileWrite);
+#endif
+			indexStore->SetTypeL(TUidType(KPermanentFileStoreLayoutUid, KUidMsvIndexFile)); // 2nd uid should be KUidMsvIndexFile
+			//
+			RStoreWriteStream writeStream;
+			// store the blank stream index in file
+			TStreamId indexStreamId = writeStream.CreateLC(*indexStore);
+			writeStream.WriteInt32L(KMsvIndexStoreVersionNumber);
+			writeStream.WriteInt32L(1000000);
+			writeStream.WriteInt32L(1);
+			writeStream.WriteInt32L(122334);
+			writeStream.CommitL();
+			CleanupStack::PopAndDestroy(); // writeStream
+			// store the commit stream value
+			TStreamId commitStreamId = writeStream.CreateLC(*indexStore);
+			writeStream.WriteInt32L(12243);
+			writeStream.CommitL();
+			CleanupStack::PopAndDestroy(); // writeStream
+			//
+			TStreamId rootIndexId = writeStream.CreateLC(*indexStore);
+			writeStream << indexStreamId;
+			writeStream << commitStreamId;
+			writeStream.CommitL();
+			CleanupStack::PopAndDestroy(); // writeStream
+			indexStore->SetRootL(rootIndexId);
+			//	
+			indexStore->CommitL();
+			delete indexStore;
+			break;
+			}
+		default:
+			iRTest(EFalse);
+		}
+	}
+
+EXPORT_C TInt CMsgServerTestUtils::IndexSizeL(TInt aDrive/* = EDriveC*/, const TDesC& aIndexFile/* = KMsvDefaultIndexFile*/)
+	{
+	TDriveUnit driveUnit(aDrive);
+	TDriveName name = driveUnit.Name();
+
+	TParse parse;
+	User::LeaveIfError(parse.Set(aIndexFile, &name, NULL));
+
+	TEntry file;
+	User::LeaveIfError(FileSession().Entry(parse.FullName(), file));
+	return file.iSize;
+	}
+
+
+EXPORT_C void CMsgServerTestUtils::Start(const TDesC& aDes)
+	{
+	iRTest.Start(aDes);
+	TestStart(++iTestNum, aDes);
+	}
+
+EXPORT_C void CMsgServerTestUtils::Next(const TDesC& aDes)
+	{
+	iRTest.Next(aDes);
+	TestStart(++iTestNum, aDes);
+	}
+
+EXPORT_C void CMsgServerTestUtils::Complete()
+	{
+	TestFinish(iTestNum, KErrNone);
+	}
+
+EXPORT_C void CMsgServerTestUtils::End()
+	{
+	iRTest.End();
+	}
+
+
+EXPORT_C void CMsgServerTestUtils::ChooseDriveL(TDriveUnit &aResult)
+	{
+	CConsoleBase &cons=*iRTest.Console();
+	CArrayFixFlat<TDriveUnit> *drives=new (ELeave) CArrayFixFlat<TDriveUnit>(5);
+	CleanupStack::PushL(drives);
+	TDriveUnit drive;
+	for (drive = EDriveC; drive < EDriveY; drive = TInt(drive) + 1)
+		{
+		TVolumeInfo info;
+		if (FileSession().Volume(info, TInt(drive)) == KErrNone)
+			{
+			drives->AppendL(drive);
+			cons.Printf(_L("%d. "),drives->Count());
+			cons.Printf(drive.Name());
+			cons.Printf(_L("\n"));
+			}
+		}
+	if(drives->Count()==0) User::Leave(KErrNotFound);
+	cons.Printf(_L("\nPlease choose a drive\n"));
+	TKeyCode ch=cons.Getch();
+	while(ch<'1' && ch > ('1'+drives->Count())) ch=cons.Getch();
+	aResult=drives->At(ch-'1');
+	CleanupStack::PopAndDestroy(drives);
+	}
+
+EXPORT_C TInt CMsgServerTestUtils::ReadInteger(const TDesC& aDes,TInt &aResult)
+	{
+	CConsoleBase &cons=*iRTest.Console();
+	_LIT(KPrompt,"%S > ");
+	cons.Printf(KPrompt,&aDes);
+	TBuf<80> number;
+	TKeyCode ch;
+	while((ch=cons.Getch())!=EKeyEnter)
+		{
+		cons.Printf(_L("%c"),ch);
+		number.Append(ch);
+		}
+	cons.Printf(_L("\n"),ch);
+	TLex lex(number);
+	return(lex.Val(aResult));
+	}
+
+
+EXPORT_C CTestScheduler::CTestScheduler() : iSchedulerActive(EFalse), iPanicSchedulerOnError(ETrue)
+	{
+
+	}
+
+
+EXPORT_C void CTestScheduler::Error(TInt aError) const
+	{
+	CTestScheduler *nonConst=CONST_CAST(CTestScheduler *,this);
+	nonConst->iSchedulerError = aError;
+	if (iSchedulerActive)
+		{
+		CActiveScheduler::Halt(KErrNone);
+		nonConst->iSchedulerActive = EFalse;
+		}
+	else
+		{
+		if (iPanicSchedulerOnError)
+			CActiveScheduler::Error(aError);
+		}
+	}
+
+
+