smsprotocols/smsstack/test/smsstacktestutilities.cpp
changeset 0 3553901f7fa8
child 14 7ef16719d8cb
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/smsprotocols/smsstack/test/smsstacktestutilities.cpp	Tue Feb 02 01:41:59 2010 +0200
@@ -0,0 +1,2267 @@
+// Copyright (c) 2003-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:
+// Utility functions for Sms Stack test harnesses
+// 
+//
+
+/**
+ @file
+*/
+
+#include <commsdattypesv1_1.h>
+#include <logcli.h>
+
+#include "smsstacktestutilities.h"
+#include <e32math.h>
+#include "smsustrm.h"
+#include "Gsmumsg.h"
+#include "smsuaddr.H"
+#include "gsmubuf.h"
+
+#include "smspdudb.h"
+#include <e32test.h>
+#include <f32file.h>
+#include "SmsuTimer.h"
+#include "smsstacklog.h"
+#include <logwraplimits.h>
+
+using namespace CommsDat;
+
+
+// Check a boolean is true
+#define LOCAL_CHECKPOINT(a) iTestStep->testBooleanTrue((a), (TText8*)__FILE__, __LINE__)
+
+// Check a boolean is true if not return error code b
+#define LOCAL_CHECKPOINT_CODE(a, b) iTestStep->testBooleanTrueWithErrorCode((a), (b), (TText8*)__FILE__, __LINE__)
+#define LOCAL_CHECKPOINT_COMPAREL(p1, p2, p3) iTestStep->TestCheckPointCompareL((p1), (p2), (p3), (TText8*)__FILE__, __LINE__)
+
+// TestExecute style Printf
+#define PRINTF1(p1)							iTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1))
+#define PRINTF2(p1, p2)						iTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1), (p2))
+#define PRINTF3(p1, p2, p3)					iTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1), (p2), (p3))
+#define PRINTF4(p1, p2, p3, p4)				iTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1), (p2), (p3), (p4))
+#define PRINTF5(p1, p2, p3, p4, p5)			iTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1), (p2), (p3), (p4), (p5))
+#define PRINTF6(p1, p2, p3, p4, p5, p6)		iTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1), (p2), (p3), (p4), (p5), (p6))
+#define PRINTF7(p1, p2, p3, p4, p5, p6, p7)	iTestStep->Logger().LogExtra(((TText8*)__FILE__), __LINE__, ESevrInfo, (p1), (p2), (p3), (p4), (p5), (p6), (p7))
+
+
+class CTSmsRegTstActive : public CActive
+	{
+public:
+	CTSmsRegTstActive();
+	~CTSmsRegTstActive();
+	void StartL();
+protected:
+	void DoCancel();
+	void RunL();
+	};
+
+CTSmsRegTstActive::CTSmsRegTstActive():
+	CActive(0)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CTSmsRegTstActive::~CTSmsRegTstActive()
+	{
+	Cancel();
+	}
+
+void CTSmsRegTstActive::DoCancel()
+	{
+	TRequestStatus* s=&iStatus;
+	User::RequestComplete(s, KErrNone);
+	}
+
+void CTSmsRegTstActive::StartL()
+	{
+	SetActive();
+	}
+
+void CTSmsRegTstActive::RunL()
+	{
+	CActiveScheduler::Stop();
+	}
+
+
+EXPORT_C CSmsStackTestUtils* CSmsStackTestUtils::NewL(CTestStep* aTestStep, RFs& aFs)
+	{
+	CSmsStackTestUtils* self = new (ELeave) CSmsStackTestUtils(aTestStep, aFs);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CSmsStackTestUtils::ConstructL()
+	{
+	iCharConv = CCnvCharacterSetConverter::NewL();
+	}
+
+EXPORT_C CSmsStackTestUtils::~CSmsStackTestUtils()
+	{
+	delete iCharConv;
+	}
+
+CSmsStackTestUtils::CSmsStackTestUtils(CTestStep* aTestStep, RFs& aFs)
+: iTestStep(aTestStep), iFs(aFs)
+	{
+	}
+
+EXPORT_C void CSmsStackTestUtils::WaitForInitializeL()
+/**
+ *  Initialize the phone for the tsy. This will prevent message sends from completing with KErrNotReady
+ */
+	{
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	CMDBSession* db = CMDBSession::NewL(KCDVersion1_2);
+#else
+	CMDBSession* db = CMDBSession::NewL(KCDVersion1_1);
+#endif
+
+	CleanupStack::PushL(db);
+
+	TName tsy;
+	TUint32 modemId = 0;
+
+	CMDBField<TUint32>* globalSettingsField = new(ELeave) CMDBField<TUint32>(KCDTIdModemPhoneServicesSMS);
+	CleanupStack::PushL(globalSettingsField);
+	globalSettingsField->SetRecordId(1);
+	globalSettingsField->LoadL(*db);
+	modemId = *globalSettingsField;
+	CleanupStack::PopAndDestroy(globalSettingsField);
+
+	CMDBField<TDesC>* tsyField = new(ELeave) CMDBField<TDesC>(KCDTIdTsyName);
+	CleanupStack::PushL(tsyField);
+	tsyField->SetRecordId(modemId);
+	tsyField->SetMaxLengthL(KMaxTextLength);
+	tsyField->LoadL(*db);
+	tsy = *tsyField;
+	CleanupStack::PopAndDestroy(tsyField);
+
+	CleanupStack::PopAndDestroy(db);
+
+	PRINTF2(_L("Loading TSY \"%S\"..."), &tsy);
+
+	RTelServer server;
+	User::LeaveIfError(server.Connect());
+	CleanupClosePushL(server);
+	User::LeaveIfError(server.LoadPhoneModule(tsy));
+
+	// Find the phone corresponding to this TSY and open a number of handles on it
+	TInt numPhones;
+	User::LeaveIfError(server.EnumeratePhones(numPhones));
+	RPhone phone;
+	TBool found=EFalse;
+
+	while (numPhones--)
+		{
+		TName phoneTsy;
+		User::LeaveIfError(server.GetTsyName(numPhones,phoneTsy));
+		if (phoneTsy.CompareF(tsy)==KErrNone)
+			{
+			PRINTF1(_L("Found RPhone..."));
+			found = ETrue;
+			RTelServer::TPhoneInfo info;
+			User::LeaveIfError(server.GetPhoneInfo(numPhones,info));
+			User::LeaveIfError(phone.Open(server,info.iName));
+			CleanupClosePushL(phone);
+			PRINTF1(_L("Initializing..."));
+			const TInt err = phone.Initialise();
+			TTimeIntervalMicroSeconds32 InitPause=9000000;  //Required Pause to Allow SMSStack to Complete its Async Init
+			User::After(InitPause);							//call to the TSY and finish its StartUp.
+			PRINTF2(_L("Completed Initialize [err=%d]"), err);
+			User::LeaveIfError(err);
+			CleanupStack::PopAndDestroy(&phone);
+			break;
+			}
+		}
+
+	LOCAL_CHECKPOINT(found);
+	CleanupStack::PopAndDestroy(&server);
+	}
+
+EXPORT_C void CSmsStackTestUtils::OpenSmsSocketLC(RSocketServ& aSocketServer, RSocket& aSocket, TSmsAddrFamily aFamily)
+/**
+ *  Initialise an RSocket for SMS
+ *  @note aSocket is pushed to CleanupStack.
+ *  @param aSocketServer reference to the socket server object
+ *  @param aSocket The socket that will be opened
+ *  @param aFamily The sms address family
+ */
+	{
+	OpenSmsSocketL(aSocketServer, aSocket, aFamily);
+	CleanupClosePushL(aSocket);
+	}
+
+EXPORT_C void CSmsStackTestUtils::OpenSmsSocketL(RSocketServ& aSocketServer, RSocket& aSocket, TSmsAddrFamily aFamily)
+/**
+ *  Initialise an RSocket for SMS, aSocket is NOT pushed to CleanupStack.
+ *  @param aSocketServer reference to the socket server object
+ *  @param aSocket The socket that will be opened
+ *  @param aFamily The sms address family
+ */
+	{
+	TSmsAddr smsaddr;
+	smsaddr.SetSmsAddrFamily(aFamily);
+	OpenSmsSocketL(aSocketServer, aSocket, smsaddr);
+	}
+
+EXPORT_C void CSmsStackTestUtils::OpenSmsSocketLC(RSocketServ& aSocketServer, RSocket& aSocket, TSmsAddr& aSmsAddr)
+/**
+ *  Initialise an RSocket for SMS.
+ *  @note aSocket is pushed to CleanupStack
+ *  @param aSocketServer reference to the socket server object
+ *  @param aSocket The socket that will be opened
+ *  @param aSmsAddr The sms address to bind to
+ */
+	{
+	OpenSmsSocketL(aSocketServer, aSocket, aSmsAddr);
+	CleanupClosePushL(aSocket);
+	}
+
+
+EXPORT_C void CSmsStackTestUtils::OpenSmsSocketL(RSocketServ& aSocketServer, RSocket& aSocket, TSmsAddr& aSmsAddr)
+/**
+ *  Initialise an RSocket for SMS, aSocket is NOT pushed to CleanupStack.
+ *  @param aSocketServer reference to the socket server object
+ *  @param aSocket The socket that will be opened
+ *  @param aSmsAddr The sms address to bind to
+ */
+	{
+	TInt ret=aSocket.Open(aSocketServer,KSMSAddrFamily,KSockDatagram,KSMSDatagramProtocol);
+	PRINTF2(_L("Socket Open Return Value : %d"),ret);
+	LOCAL_CHECKPOINT(ret == KErrNone);
+	CleanupClosePushL(aSocket);
+	ret=aSocket.Bind(aSmsAddr);
+	PRINTF2(_L("Socket Bind Return Value : %d"),ret);
+	LOCAL_CHECKPOINT(ret == KErrNone);
+	WaitForInitializeL();
+	CleanupStack::Pop(&aSocket);
+	}
+
+EXPORT_C void CSmsStackTestUtils::SendSmsAndChangeBearerL(CSmsMessage* aSms, RSocket& aSocket, RMobileSmsMessaging::TMobileSmsBearer aBearer)
+/**
+ *  Stream aSms out to the socket server. The idea is to change bearer midway through
+ *  sending the PDUs making up the complete message.
+ *  @param aSms contains the sms tpdu that will be streamed to the sms stack
+ *  @param aSocket is used to stream the aSms to the sms stack
+ *  @param aBearer Bearer setting that is changed to CommDb
+ *  @leave Leaves if streaming the message to the socket server doesn't succeed
+ *  @leave Leaves if sending is completed with error code
+ */
+	{
+	RSmsSocketWriteStream writestream(aSocket);
+	TRAPD(ret,writestream << *aSms);
+	LOCAL_CHECKPOINT(ret == KErrNone);
+	TRAP(ret,writestream.CommitL());
+	LOCAL_CHECKPOINT(ret == KErrNone);
+
+    // Create comms database object
+	CMDBSession* db = CMDBSession::NewL(KCDVersion1_1);
+	CleanupStack::PushL(db);
+
+ 	//Send message and change bearer
+	TPckgBuf<TUint> sbuf;
+	TRequestStatus status;
+	aSocket.Ioctl(KIoctlSendSmsMessage,status,&sbuf, KSolSmsProv);
+
+	//Wait couple of seconds to ensure first pdus of message have been sent
+	User::After(2500000);
+
+	// Change bearer
+	CMDBField<TUint32>* smsBearerField = new(ELeave) CMDBField<TUint32>(KCDTIdSMSBearer);
+	CleanupStack::PushL(smsBearerField);
+	smsBearerField->SetRecordId(1); //it's GlobalSettingsRecord
+	*smsBearerField = aBearer;
+	smsBearerField->ModifyL(*db);
+	CleanupStack::PopAndDestroy(smsBearerField);
+	CleanupStack::PopAndDestroy(db);
+
+	User::WaitForRequest(status);
+	PRINTF2(_L("SendSmsL - sendSmsMessage returned %d"), status.Int());
+	LOCAL_CHECKPOINT(status.Int() == KErrNone);
+
+	CSmsBuffer& smsbuffer = (CSmsBuffer&)aSms->Buffer();
+	TInt len = smsbuffer.Length();
+	HBufC* hbuf = HBufC::NewL(len);
+	TPtr ptr = hbuf->Des();
+	smsbuffer.Extract(ptr,0,len);
+	PRINTF2(_L("SMS contains %d characters"),len);
+	delete hbuf;
+	}
+
+EXPORT_C void CSmsStackTestUtils::ChangeBearerL(RMobileSmsMessaging::TMobileSmsBearer aBearer)
+/**
+Change the bearer in CommDB global settings.
+
+@param aBearer The new bearer setting.
+@return none
+*/
+	{
+	// Start a CommDB session
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	CMDBSession* db = CMDBSession::NewL(KCDVersion1_2);
+#else
+	CMDBSession* db = CMDBSession::NewL(KCDVersion1_1);
+#endif
+	CleanupStack::PushL(db);
+	
+	// Change bearer in global settings
+	CMDBRecordSet<CCDGlobalSettingsRecord> globalSettingsRecord(KCDTIdGlobalSettingsRecord);
+	TRAPD(err, globalSettingsRecord.LoadL(*db));
+	if (err != KErrNone)
+		{
+		PRINTF2(_L("Could not load global settings. Error = %d\n"), err);
+		User::Leave(err);
+		}
+	((CCDGlobalSettingsRecord*)globalSettingsRecord.iRecords[0])->iSMSBearer = aBearer;
+	globalSettingsRecord.ModifyL(*db);
+	
+	PRINTF2(_L("Setting bearer in global settings to %d\n"), aBearer); 
+	
+	CleanupStack::PopAndDestroy(db);
+	}
+
+EXPORT_C void CSmsStackTestUtils::GetBearerL(RMobileSmsMessaging::TMobileSmsBearer& aBearer)
+/**
+Get the bearer from CommDB global settings.
+
+@param aBearer The bearer setting retrieved from global settings.
+@return none
+*/
+	{
+	// Start a CommDB session
+#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
+	CMDBSession* db = CMDBSession::NewL(KCDVersion1_2);
+#else
+	CMDBSession* db = CMDBSession::NewL(KCDVersion1_1);
+#endif
+	CleanupStack::PushL(db);
+	
+	// Load global settings
+	CMDBRecordSet<CCDGlobalSettingsRecord> globalSettingsRecord(KCDTIdGlobalSettingsRecord);
+	TRAPD(err, globalSettingsRecord.LoadL(*db));
+	if (err != KErrNone)
+		{
+		PRINTF2(_L("Could not load global settings. Error = %d\n"), err);
+		User::Leave(err);
+		}
+	TInt tempBearer = ((CCDGlobalSettingsRecord*)globalSettingsRecord.iRecords[0])->iSMSBearer;
+	aBearer = static_cast<RMobileSmsMessaging::TMobileSmsBearer>(tempBearer);
+	PRINTF2(_L("Got bearer from CommDB. Bearer = %d\n"), aBearer);
+	
+	CleanupStack::PopAndDestroy(db);
+	}
+
+EXPORT_C void CSmsStackTestUtils::DisableLogging()
+ 	{
+ 	CTSmsRegTstActive* testActive = new(ELeave)CTSmsRegTstActive();
+ 	CleanupStack::PushL(testActive);
+ 	testActive->StartL();	
+ 
+ 	CLogWrapper* logWrapper=CLogWrapper::NewL(iFs);
+ 	CleanupStack::PushL(logWrapper);
+ 	CLogClient& logClient = static_cast<CLogClient&>(logWrapper->Log());
+ 	TLogConfig config;
+ 	logClient.GetConfig(config, testActive->iStatus);
+ 	CActiveScheduler::Start();
+ 	LOCAL_CHECKPOINT(testActive->iStatus.Int() == KErrNone);
+ 
+ 	// Disable logging
+ 	config.iMaxEventAge = 0;
+ 	config.iMaxLogSize = 0;
+ 	config.iMaxRecentLogSize = 0;
+ 
+ 	testActive->StartL();
+ 	logClient.ChangeConfig(config, testActive->iStatus);
+ 	CActiveScheduler::Start();
+ 	LOCAL_CHECKPOINT(testActive->iStatus.Int() == KErrNone);
+ 	
+ 	CleanupStack::PopAndDestroy(logWrapper);	
+ 	CleanupStack::PopAndDestroy(testActive);
+	}
+ 
+ EXPORT_C void CSmsStackTestUtils::EnableLogging()
+ 	{
+ 	CTSmsRegTstActive* testActive = new(ELeave)CTSmsRegTstActive();
+ 	CleanupStack::PushL(testActive);
+ 	testActive->StartL();	
+ 
+ 	CLogWrapper* logWrapper=CLogWrapper::NewL(iFs);
+ 	CleanupStack::PushL(logWrapper);
+ 	CLogClient& logClient = static_cast<CLogClient&> (logWrapper->Log());
+ 	TLogConfig config;
+ 	logClient.GetConfig(config, testActive->iStatus);
+ 	CActiveScheduler::Start();
+ 	LOCAL_CHECKPOINT(testActive->iStatus.Int() == KErrNone);
+ 
+ 	// Enable logging
+ 	config.iMaxEventAge = 10000;
+ 	config.iMaxLogSize  = 10000; 
+ 	config.iMaxRecentLogSize = 127; 
+ 	
+ 	testActive->StartL();	
+ 	logClient.ChangeConfig(config, testActive->iStatus);
+ 	CActiveScheduler::Start();
+ 	LOCAL_CHECKPOINT(testActive->iStatus.Int() == KErrNone);
+ 	
+ 	CleanupStack::PopAndDestroy(logWrapper);	
+ 	CleanupStack::PopAndDestroy(testActive);
+ }		
+	
+	
+EXPORT_C void CSmsStackTestUtils::GetLogEventL(CLogEvent& aLogEvent, TInt aLogServerId)
+/**
+ *  Get SMS log event from event logger.
+ *  @param aLogEvent reference to the CLogEvent object
+ *  @param aLogServerId number of log event
+ */
+	{
+	CTSmsRegTstActive* testActive = new(ELeave)CTSmsRegTstActive();
+	CleanupStack::PushL(testActive);
+
+	CLogWrapper* logWrapper=CLogWrapper::NewL(iFs);
+	CleanupStack::PushL(logWrapper);
+
+	aLogEvent.SetId(aLogServerId);
+	testActive->StartL();
+	logWrapper->Log().GetEvent(aLogEvent,testActive->iStatus);
+	CActiveScheduler::Start();
+	LOCAL_CHECKPOINT(testActive->iStatus.Int() == KErrNone);
+	CleanupStack::PopAndDestroy(2);	// testActive, logWrapper
+	}
+
+EXPORT_C TLogId CSmsStackTestUtils::AddLogEventL(CSmsMessage& aSmsMessage,TLogSmsPduData& aSmsPDUData)
+/**
+ *  Add SMS log event to the event logger.
+ *  @param aSmsMessage SM mesage
+ *  @param aLogSmsPduData initialised structure  with data relevant to logging
+ */
+	{
+	CTSmsRegTstActive* testActive = new(ELeave)CTSmsRegTstActive();
+	CleanupStack::PushL(testActive);
+
+	CLogWrapper* logWrapper=CLogWrapper::NewL(iFs);
+	CleanupStack::PushL(logWrapper);
+
+	TLogId id=NULL;
+
+	if(logWrapper->ClientAvailable())
+	{
+		testActive->StartL();
+
+
+		CLogEvent* logevent=CLogEvent::NewL();
+		CleanupStack::PushL(logevent);
+
+		TBuf<KLogMaxDirectionLength> direction;
+		User::LeaveIfError(logWrapper->Log().GetString(direction,R_LOG_DIR_OUT));
+
+
+		logevent->SetDirection(direction);
+		logevent->SetEventType(KLogShortMessageEventTypeUid);
+		logevent->SetNumber(aSmsMessage.ToFromAddress());
+
+		logevent->SetSubject(_L("test"));
+		logevent->SetStatus(_L("status"));
+		TPckg<TLogSmsPduData> packeddata(aSmsPDUData);
+		logevent->SetDataL(packeddata);
+
+		logWrapper->Log().AddEvent(*logevent,testActive->iStatus);
+		CActiveScheduler::Start();
+		LOCAL_CHECKPOINT(testActive->iStatus.Int() == KErrNone);
+		id=logevent->Id();
+		CleanupStack::PopAndDestroy(logevent);
+	}
+
+	CleanupStack::PopAndDestroy(2);	// testActive, logWrapper
+	return id;
+	}
+
+
+EXPORT_C void CSmsStackTestUtils::CopyConfigFileL(const TDesC& aFromSmsConfigFile, CSmsPduDatabase* aPduDb)
+	{
+	PRINTF3(_L("Copying %S to %S..."), &aFromSmsConfigFile, &KSimTsyConfigFileName);
+	TBool createdDb = EFalse;
+
+	if (aPduDb == NULL)
+		{
+		aPduDb = CSmsPduDatabase::NewL(iFs);
+		CleanupStack::PushL(aPduDb);
+		createdDb = ETrue;
+		}
+
+	aPduDb->RewriteFileL(aFromSmsConfigFile, KGmsSmsConfigFileDir, KSimTsyConfigFileName);
+	PRINTF1(_L("done"));
+
+	if (createdDb)
+		CleanupStack::PopAndDestroy(aPduDb);
+	}
+
+
+EXPORT_C CSmsMessage* CSmsStackTestUtils::CreateSmsMessageLC(CSmsPDU::TSmsPDUType aType, const TDesC& aDestination, const TDesC& aMessage)
+	{
+	CSmsBuffer* buffer = CSmsBuffer::NewL();
+	buffer->InsertL(0, aMessage);
+
+	CSmsMessage* message = CSmsMessage::NewL(iFs, aType, buffer);
+	CleanupStack::PushL(message);
+
+	message->SetToFromAddressL(aDestination);
+
+	return message;
+	}
+
+EXPORT_C void CSmsStackTestUtils::AddSmsRxL(CTestConfig& aConfigFile, TInt aTestNumber, CSmsMessage& aMessage, const TDesC& aServiceCenter) const
+	{
+	_LIT8(KSmspTestUtilsSmsRx, "SmsRx");
+	_LIT8(KSmspTestUtilsSmsRxFormat, "%S, %S");
+
+	CTestConfigSection& section = GetSectionL(aConfigFile, aTestNumber);
+
+	CArrayFixFlat<TGsmSms>* pdus = EncodeMessageLC(aMessage);
+
+	const TInt pduCount = pdus->Count();
+
+	for (TInt i = 0; i < pduCount; i++)
+		{
+		const TGsmSms& pdu = (*pdus)[i];
+
+		HBufC8* pduBuf = ConvertToHexLC(pdu.Pdu());
+
+		HBufC8* sc = HBufC8::NewLC(aServiceCenter.Length());
+		sc->Des().Copy(aServiceCenter);
+
+		const TInt maxLen = KSmspTestUtilsSmsRxFormat().Length() + pduBuf->Length() + sc->Length();
+		HBufC8* smsRx = HBufC8::NewLC(maxLen);
+
+		smsRx->Des().AppendFormat(KSmspTestUtilsSmsRxFormat, pduBuf, sc);
+
+		CTestConfigItem* item = CTestConfigItem::NewLC(section, KSmspTestUtilsSmsRx, *smsRx);
+
+		User::LeaveIfError(section.Items().Append(item));
+
+		CleanupStack::Pop(item);
+		CleanupStack::PopAndDestroy(smsRx);
+		CleanupStack::PopAndDestroy(sc);
+		CleanupStack::PopAndDestroy(pduBuf);
+		}
+
+	CleanupStack::PopAndDestroy(pdus);
+	}
+
+EXPORT_C CTestConfigSection& CSmsStackTestUtils::GetSectionL(CTestConfig& aConfigFile, TInt aTestNumber) const
+	{
+	_LIT8(KSmspTestUtilsTest, "test%d");
+
+	TBuf8<16> test;
+	test.AppendFormat(KSmspTestUtilsTest, aTestNumber);
+	CTestConfigSection* section = aConfigFile.Section(test);
+
+	if (section == NULL)
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	return *section;
+	}
+
+EXPORT_C void CSmsStackTestUtils::AddSmsTxL(CTestConfig& aConfigFile, TInt aTestNumber, CSmsMessage& aMessage, const TDesC& aServiceCenter, TInt aMsgRef, CSmsMessage* aSubmitReport, TInt aExpectedError) const
+	{
+	_LIT8(KSmspTestUtilsSmsTx, "SmsTx");
+	_LIT8(KSmspTestUtilsSmsTxFormat, "%S, %S, %d, %S, %d");
+
+	CTestConfigSection& section = GetSectionL(aConfigFile, aTestNumber);
+	CArrayFixFlat<TGsmSms>* pdus = EncodeMessageLC(aMessage);
+
+	HBufC8* submitReport = NULL;
+
+	if (aSubmitReport == NULL)
+		{
+		submitReport = KNullDesC8().AllocLC();
+		}
+	else
+		{
+		CArrayFixFlat<TGsmSms>* srPdus = EncodeMessageLC(*aSubmitReport);
+		const TGsmSms& pdu = (*srPdus)[0];
+		submitReport = ConvertToHexLC(pdu.Pdu());
+		CleanupStack::Pop(submitReport);
+		CleanupStack::PopAndDestroy(srPdus);
+		CleanupStack::PushL(submitReport);
+		}
+
+	const TInt pduCount = pdus->Count();
+
+	for (TInt i = 0; i < pduCount; i++)
+		{
+		const TGsmSms& pdu = (*pdus)[i];
+		HBufC8* pduBuf = ConvertToHexLC(pdu.Pdu());
+
+		HBufC8* sc = HBufC8::NewLC(aServiceCenter.Length());
+		sc->Des().Copy(aServiceCenter);
+
+		const TInt maxLen = KSmspTestUtilsSmsTxFormat().Length() + pduBuf->Length() + sc->Length() + submitReport->Length();
+		HBufC8* smsTx = HBufC8::NewLC(maxLen);
+
+		smsTx->Des().AppendFormat(KSmspTestUtilsSmsTxFormat, pduBuf, sc, aMsgRef, submitReport, aExpectedError);
+
+		CTestConfigItem* item = CTestConfigItem::NewLC(section, KSmspTestUtilsSmsTx, *smsTx);
+
+		User::LeaveIfError(section.Items().Append(item));
+
+		CleanupStack::Pop(item);
+		CleanupStack::PopAndDestroy(smsTx);
+		CleanupStack::PopAndDestroy(sc);
+		CleanupStack::PopAndDestroy(pduBuf);
+		}
+
+	CleanupStack::PopAndDestroy(submitReport);
+	CleanupStack::PopAndDestroy(pdus);
+	}
+
+EXPORT_C HBufC8* CSmsStackTestUtils::ConvertToHexLC(const TDesC8& aDes) const
+	{
+	const TInt len = aDes.Length();
+
+	HBufC8* hBuf = HBufC8::NewLC(len*2);
+	TPtr8 value(hBuf->Des());
+
+	for (TInt i = 0; i < len; i++)
+		{
+		value.AppendFormat(_L8("%02X"), aDes[i]);
+		}
+
+	return hBuf;
+	}
+
+CArrayFixFlat<TGsmSms>* CSmsStackTestUtils::EncodeMessageLC(CSmsMessage& aMessage) const
+	{
+	CArrayFixFlat<TGsmSms>* array = new (ELeave) CArrayFixFlat<TGsmSms>(1);
+	CleanupStack::PushL(array);
+	aMessage.EncodeMessagePDUsL(*array);
+	return array;
+	}
+
+EXPORT_C TSmsFirstOctet CSmsStackTestUtils::FirstDeliverOctet(TBool aMMS, TBool aRP, TBool aUDHI, TBool aSRI)
+	{
+	TSmsFirstOctet firstOctet(0);
+
+	if (!aMMS)
+		firstOctet = firstOctet | TSmsFirstOctet::ESmsNoMoreMessagesToSend;
+
+	if (aRP)
+		firstOctet = firstOctet | TSmsFirstOctet::ESmsReplyPathExists;
+
+	if (aUDHI)
+		firstOctet = firstOctet | TSmsFirstOctet::ESmsUDHIHeaderPresent;
+
+	if (aSRI)
+		firstOctet = firstOctet | TSmsFirstOctet::ESmsStatusReportRequested;
+
+	return firstOctet;
+	}
+
+EXPORT_C void CSmsStackTestUtils::DeliverWithoutUserDataL(TGsmSms& aPdu, TSmsFirstOctet aFO, const TGsmSmsTelNumber& aOA, TSmsProtocolIdentifier aPID, TSmsDataCodingScheme aDCS, const TTime& aSCTS, TInt aUTCOffset)
+	{
+	RMobileSmsMessaging::TMobileSmsGsmTpdu pdu;
+	pdu.SetLength(pdu.MaxLength());
+	TUint8* ptr0 = &pdu[0];
+	TUint8* ptr1 = ptr0;
+
+	//Prepare the OA
+	CSmsAddress* addr = CSmsAddress::NewL(*iCharConv, iFs);
+	CleanupStack::PushL(addr);
+	addr->SetParsedAddressL(aOA);
+
+	//Prepare the service center time stamp
+	TSmsServiceCenterTimeStamp time;
+	time.SetTime(aSCTS);
+	time.SetTimeOffset(aUTCOffset);
+
+	//Encode the PDU. Unfortunately this relies on GSMU.
+	ptr1 = aFO.EncodeL(ptr1);
+	ptr1 = addr->EncodeL(ptr1);
+	ptr1 = aPID.EncodeL(ptr1);
+	ptr1 = aDCS.EncodeL(ptr1);
+	ptr1 = time.EncodeL(ptr1);
+	pdu.SetLength(ptr1 - ptr0);
+	aPdu.SetPdu(pdu);
+
+	CleanupStack::PopAndDestroy(addr);
+	}
+
+
+/**
+ *  This is a unit test for class TSmsServiceCenterTimeStamp.  It is added to this utility
+ *  class because it has access to TSmsServiceCenterTimeStamp.  TSmsServiceCenterTimeStamp is not exported
+ *  out of the gsmsu.dll.  This is why this project compiles with gsmsuelem.cpp.
+ */
+EXPORT_C void CSmsStackTestUtils::CreateTSmsServiceCenterTimeStampL()
+	{
+	//Prepare the service center time stamp
+	TSmsServiceCenterTimeStamp serviceCenterTime;
+	TTime utcTime;
+	TInt offset=0;
+	utcTime.UniversalTime();
+
+	//	Set and Get
+	serviceCenterTime.SetTime(utcTime);
+	serviceCenterTime.SetTimeOffset(offset);
+
+	TTime testTimeValue=serviceCenterTime.Time();
+	TInt testOffsetValue=serviceCenterTime.TimeOffset();
+
+	LOCAL_CHECKPOINT(testTimeValue==utcTime);
+	LOCAL_CHECKPOINT(testOffsetValue==offset);
+
+	//boundary value checks
+	//Offset is stored in number of quarter hours.
+	//Max/Min value = +/- 79
+	//This is the maximum value specified in the spec 3GPP TS23.040
+	//The biggest value allowed by the production code is KSmsMaxTimeZoneNumQuarterHours=79
+	//This is the maximum value that can be stored in the PDU when encoded.  Actual max byte
+	//storage space available.  The test will check that this maximum will be allowable.
+	//Values beyond 79 will cause the thread to panic
+	TInt positiveValue=79;
+	TInt negativeValue=-79;
+
+	serviceCenterTime.SetTimeOffset(positiveValue);
+	testOffsetValue=serviceCenterTime.TimeOffset();
+	LOCAL_CHECKPOINT(testOffsetValue==positiveValue);
+
+	serviceCenterTime.SetTimeOffset(negativeValue);
+	testOffsetValue=serviceCenterTime.TimeOffset();
+	LOCAL_CHECKPOINT(testOffsetValue==negativeValue);
+
+	//Try past the end.  This panics the test case.  It has been done as a check to test
+	// a panic will be raised.
+/*	TInt overFlowValue=80;
+	serviceCenterTime.SetTimeOffset(overFlowValue);
+
+	TInt underFlowValue=-99;
+	serviceCenterTime.SetTimeOffset(underFlowValue);
+*/
+	}
+
+EXPORT_C void CSmsStackTestUtils::DecodeTSmsServiceCenterTimeStampL()
+	{
+	//Decode timestamp
+	TTimeIntervalSeconds oneSecond(1);
+	const TInt KTimeStampSize=7;
+	TInt ret=0;
+	TBuf8<KTimeStampSize> encodedPdu;
+	encodedPdu.SetLength(encodedPdu.MaxLength());
+
+	//---------------------------------------------------
+	//Decode a valid service center time stamp
+	//Expected UTC = 29/02/2004, 15h30m0s, offset=3hrs
+	//Local Time   = 29/02/2004, 18h30m0s
+	TDateTime utcDateTime(2004,EFebruary,28,15,30,0,0);
+	TTime expectedDecodedTime(utcDateTime);
+
+	encodedPdu[0]=0x40;		//year=2004
+	encodedPdu[1]=0x20;		//month=Feb
+	encodedPdu[2]=0x92;		//day=29th
+	encodedPdu[3]=0x81;		//hour=18h
+	encodedPdu[4]=0x03;		//minute=30min
+	encodedPdu[5]=0x00;		//second=0
+	encodedPdu[6]=0x21;		//timeZone=12x15min=3hrs
+
+	//Decode the service center time stamp.  This must equal the expected
+	TGsmuLex8 pduTime(encodedPdu);
+	TSmsServiceCenterTimeStamp serviceCenterTimeStamp;
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrNone);
+
+	//Compare the times
+	TTime time=serviceCenterTimeStamp.Time();
+	LOCAL_CHECKPOINT(time==expectedDecodedTime);
+
+	//Check the offset
+	TInt offset=serviceCenterTimeStamp.TimeOffset();
+	LOCAL_CHECKPOINT(offset==12);
+
+	//---------------------------------------------------
+	//Decode a negative offset
+	//Expected UTC = 29/02/2004, 15h30m0s, offset=-5hrs
+	//Local Time   = 29/02/2004, 10h30m0s
+
+	encodedPdu[0]=0x40;		//year=2004
+	encodedPdu[1]=0x20;		//month=Feb
+	encodedPdu[2]=0x92;		//day=29
+	encodedPdu[3]=0x01;		//hour=10
+	encodedPdu[4]=0x03;		//minute=30
+	encodedPdu[5]=0x00;		//second
+	encodedPdu[6]=0x0A;		//timeZone=-5hrs=15minx20, 4th bit is 1 for negative
+
+
+	//Decode the service center time stamp.  This must equal the expected
+	pduTime=TGsmuLex8(encodedPdu);
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrNone);
+
+	//Compare the times
+	time=serviceCenterTimeStamp.Time();
+	LOCAL_CHECKPOINT(time==expectedDecodedTime);
+
+	//Check the offset
+	offset=serviceCenterTimeStamp.TimeOffset();
+	LOCAL_CHECKPOINT(offset==-20);
+
+	//---------------------------------------------------
+	//Decode time stamp over new year
+	//
+	//Expected UTC = 01/01/2005, 00h15m0s, offset=-1h15m
+	//Local Time   = 31/12/2004, 23h00m0s
+	utcDateTime=TDateTime(2005,EJanuary,0,0,15,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	encodedPdu[0]=0x40;		//year=2004
+	encodedPdu[1]=0x21;		//month=December=12
+	encodedPdu[2]=0x13;		//day=31
+	encodedPdu[3]=0x32;		//hour=23hrs
+	encodedPdu[4]=0x00;		//minute=0
+	encodedPdu[5]=0x00;		//second=0
+	encodedPdu[6]=0x58;		//timeZone is -5.
+								//	-5x15min=-1hr15min
+
+	//Decode the service center time stamp.  This must equal the expected
+	pduTime=TGsmuLex8(encodedPdu);
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrNone);
+
+	//Compare the times
+	time=serviceCenterTimeStamp.Time();
+	LOCAL_CHECKPOINT(time==expectedDecodedTime);
+
+	//Check the offset
+	offset=serviceCenterTimeStamp.TimeOffset();
+	LOCAL_CHECKPOINT(offset==-5);
+
+	//---------------------------------------------------
+	//Decode over leap year
+
+	//Expected UTC = 29/02/2004, 21h00m0s, offset=+5h 30min 0s
+	//Local Time   = 01/03/2004, 02h30m0s
+	utcDateTime=TDateTime(2004,EFebruary,28,21,0,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	//	local time is 01/03/2004   2hrs 30
+	encodedPdu[0]=0x40;		//year=2004
+	encodedPdu[1]=0x30;		//month=March
+	encodedPdu[2]=0x10;		//day=1st
+	encodedPdu[3]=0x20;		//hour=2hrs
+	encodedPdu[4]=0x03;		//minute=30min
+	encodedPdu[5]=0x00;		//second=0
+	encodedPdu[6]=0x22;		//timeZone is 5hrs30min.
+							//	22x15min=5hr30min
+
+	pduTime=TGsmuLex8(encodedPdu);
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrNone);
+
+	//Compare the times
+	time=serviceCenterTimeStamp.Time();
+	LOCAL_CHECKPOINT(time==expectedDecodedTime);
+
+	//Check the offset
+	offset=serviceCenterTimeStamp.TimeOffset();
+	LOCAL_CHECKPOINT(offset==22);
+
+	//---------------------------------------------------
+	//DecodeL a corrupt time stamp
+	encodedPdu[0]=0x40;		//year
+	encodedPdu[1]=0x02;		//month = 20
+	encodedPdu[2]=0x96;		//day = 69
+	encodedPdu[3]=0x51;		//hour
+	encodedPdu[4]=0x03;		//minute
+	encodedPdu[5]=0;			//second
+	encodedPdu[6]=0x20;		//timezone=12
+
+	//Decode should fail trying to recreate the time.
+	pduTime=TGsmuLex8(encodedPdu);
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrGeneral);
+
+	//---------------------------------------------------
+	//DecodeL a zero offset
+
+	//Expected UTC = 15/06/2004, 14h20, offset = 0
+	//Local Time   = 15/06/2004, 14h20
+	utcDateTime=TDateTime(2004,EJune,14,14,20,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	encodedPdu[0]=0x40;		//year=2004
+	encodedPdu[1]=0x60;		//month=06
+	encodedPdu[2]=0x51;		//day=15
+	encodedPdu[3]=0x41;		//hour=14
+	encodedPdu[4]=0x02;		//minute=20
+	encodedPdu[5]=0x00;		//second=0
+	encodedPdu[6]=0x00;		//timezone=0
+
+	//Decode should bring back the same date.  ie. local time==utc time
+	pduTime=TGsmuLex8(encodedPdu);
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrNone);
+
+	//Compare the times
+	time=serviceCenterTimeStamp.Time();
+	LOCAL_CHECKPOINT(time==expectedDecodedTime);
+
+	//Check the offset
+	offset=serviceCenterTimeStamp.TimeOffset();
+	LOCAL_CHECKPOINT(offset==0);
+
+	//---------------------------------------------------
+	//DecodeL a maximum possitive offset
+
+	//Expected UTC = 15/06/2004, 01h20, offset = 19h45min
+	//Local Time   = 15/06/2004, 21h05
+	utcDateTime=TDateTime(2004,EJune,14,01,20,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	encodedPdu[0]=0x40;		//year=2004
+	encodedPdu[1]=0x60;		//month=06
+	encodedPdu[2]=0x51;		//day=15
+	encodedPdu[3]=0x12;		//hour=21
+	encodedPdu[4]=0x50;		//minute=05
+	encodedPdu[5]=0x00;		//second=0
+	encodedPdu[6]=0x97;		//timezone=79x15min=19h45
+							//offset = 1185 minutes = 19h45min
+
+	//Decode should bring back the same date.  ie. local time==utc time
+	pduTime=TGsmuLex8(encodedPdu);
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrNone);
+
+	//Compare the times
+	time=serviceCenterTimeStamp.Time();
+	LOCAL_CHECKPOINT(time==expectedDecodedTime);
+
+	//Check the offset
+	offset=serviceCenterTimeStamp.TimeOffset();
+	LOCAL_CHECKPOINT(offset==79);
+
+	//---------------------------------------------------
+	//DecodeL a maximum negative offset
+
+	//Expected UTC = 15/06/2004, 23h45, offset = -19h45min
+	//Local Time   = 15/06/2004, 04h00
+	utcDateTime=TDateTime(2004,EJune,14,23,45,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	encodedPdu[0]=0x40;		//year=2004
+	encodedPdu[1]=0x60;		//month=06
+	encodedPdu[2]=0x51;		//day=15
+	encodedPdu[3]=0x40;		//hour=4
+	encodedPdu[4]=0x00;		//minute=0
+	encodedPdu[5]=0x00;		//second=0
+	encodedPdu[6]=0x9F;		//timezone=-79x15min=-19h45
+							//offset = -1185 minutes = 19h45min
+
+	//Decode should bring back the same date.  ie. local time==utc time
+	pduTime=TGsmuLex8(encodedPdu);
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrNone);
+
+	//Compare the times
+	time=serviceCenterTimeStamp.Time();
+	LOCAL_CHECKPOINT(time==expectedDecodedTime);
+
+	//Check the offset
+	offset=serviceCenterTimeStamp.TimeOffset();
+	LOCAL_CHECKPOINT(offset==-79);
+	
+	//---------------------------------------------------
+	//DecodeL a timestamp with an invalid offset 0xFF.
+
+	//Expected UTC = 15/06/2004, 14h20, offset = 0
+	//Local Time   = 15/06/2004, 14h20
+	utcDateTime=TDateTime(2004,EJune,14,14,20,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+	
+	encodedPdu[0]=0x40;		//year=2004
+	encodedPdu[1]=0x60;		//month=06
+	encodedPdu[2]=0x51;		//day=15
+	encodedPdu[3]=0x41;		//hour=14
+	encodedPdu[4]=0x02;		//minute=20
+	encodedPdu[5]=0x00;		//second=0
+	encodedPdu[6]=0xFF;		//timezone off set is invalid, so set to zero
+	
+	//Decode should bring back the same date.  ie. local time==utc time
+	pduTime=TGsmuLex8(encodedPdu);
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrNone);
+
+	//Compare the times
+	time=serviceCenterTimeStamp.Time();
+	LOCAL_CHECKPOINT(time==expectedDecodedTime);
+	
+	//Check the offset
+	offset=serviceCenterTimeStamp.TimeOffset();
+	LOCAL_CHECKPOINT(offset==0);
+	
+	//---------------------------------------------------
+	//DecodeL a timestamp with an invalid offset 0xAF
+
+	//Expected UTC = 15/06/2004, 14h20, offset = 0
+	//Local Time   = 15/06/2004, 14h20
+	utcDateTime=TDateTime(2004,EJune,14,14,20,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+	
+	encodedPdu[0]=0x40;		//year=2004
+	encodedPdu[1]=0x60;		//month=06
+	encodedPdu[2]=0x51;		//day=15
+	encodedPdu[3]=0x41;		//hour=14
+	encodedPdu[4]=0x02;		//minute=20
+	encodedPdu[5]=0x00;		//second=0
+	encodedPdu[6]=0xAF;		//timezone off set is invalid, so set to zero
+	
+	//Decode should bring back the same date.  ie. local time==utc time
+	pduTime=TGsmuLex8(encodedPdu);
+	serviceCenterTimeStamp.DecodeL(pduTime,ret);
+	LOCAL_CHECKPOINT(ret==KErrNone);
+
+	//Compare the times
+	time=serviceCenterTimeStamp.Time();
+	LOCAL_CHECKPOINT(time==expectedDecodedTime);
+	
+	//Check the offset
+	offset=serviceCenterTimeStamp.TimeOffset();
+	LOCAL_CHECKPOINT(offset==0);
+	}
+
+
+EXPORT_C void CSmsStackTestUtils::EncodeTSmsServiceCenterTimeStampL()
+	{
+	//Encode timestamp
+	const TInt KServiceCenterBuffSizeInPDU=7;			//Buffer is a 14 semi-octet buffer, 7 byte
+	TBuf8<KServiceCenterBuffSizeInPDU> encodedPdu;
+	encodedPdu.SetLength(encodedPdu.MaxLength());
+	TUint8* ptr = &encodedPdu[0];
+
+	//---------------------------------------------------
+	//Expected UTC = 03/03/2005, 12h00, offset = 3hrs
+	//Local Time   = 03/03/2005, 15h00
+	TMonth month=EMarch;
+	TDateTime utcDateTime(2005,month,2,12,0,0,0);
+	TTime expectedDecodedTime(utcDateTime);
+
+	//Prepare the service center time stamp
+	TSmsServiceCenterTimeStamp time;
+	time.SetTime(expectedDecodedTime);
+
+	//Set offset=+12, +3hrs
+	time.SetTimeOffset(12);
+
+	//Encode the PDU.
+	time.EncodeL(ptr);
+
+	//	This is the expected structure in bytes for the time above
+	TUint8 semioctet = encodedPdu[0];	//2005
+	LOCAL_CHECKPOINT(semioctet==0x50);
+	semioctet = encodedPdu[1];			//March
+	LOCAL_CHECKPOINT(semioctet==0x30);
+	semioctet = encodedPdu[2];			//3rd
+	LOCAL_CHECKPOINT(semioctet==0x30);
+	semioctet = encodedPdu[3];			//15h
+	LOCAL_CHECKPOINT(semioctet==0x51);
+	semioctet = encodedPdu[4];			//min
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = encodedPdu[5];			//sec
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = encodedPdu[6];			//offset
+	LOCAL_CHECKPOINT(semioctet==0x21);
+
+
+	//---------------------------------------------------
+	//Expected UTC = 01/03/2005, 01h00, offset = -3hrs
+	//Local Time   = 28/02/2005, 22h00
+	encodedPdu.Delete(0,encodedPdu.MaxLength());
+	encodedPdu.SetLength(encodedPdu.MaxLength());
+	ptr = &encodedPdu[0];
+
+	utcDateTime=TDateTime(2005,month,0,1,0,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	//Prepare the service center time stamp
+	time.SetTime(expectedDecodedTime);
+
+	//Set offset=-12, -3hrs
+	time.SetTimeOffset(-12);
+
+	//Encode the PDU.
+	time.EncodeL(ptr);
+
+	//	This is the expected structure in bytes for the time above
+	semioctet = encodedPdu[0];			//2005
+	LOCAL_CHECKPOINT(semioctet==0x50);
+	semioctet = encodedPdu[1];			//Feb
+	LOCAL_CHECKPOINT(semioctet==0x20);
+	semioctet = encodedPdu[2];			//28th
+	LOCAL_CHECKPOINT(semioctet==0x82);
+	semioctet = encodedPdu[3];			//22h
+	LOCAL_CHECKPOINT(semioctet==0x22);
+	semioctet = encodedPdu[4];			//min
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = encodedPdu[5];			//sec
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = encodedPdu[6];			//offset
+	LOCAL_CHECKPOINT(semioctet==0x29);
+
+
+	//---------------------------------------------------
+	//Expected UTC = 31/12/2005, 23h45min55s, offset = +3h15min
+	//Local Time   = 01/01/2006, 03h00min55s
+	encodedPdu.Delete(0,encodedPdu.MaxLength());
+	encodedPdu.SetLength(encodedPdu.MaxLength());
+	ptr = &encodedPdu[0];
+	month=EDecember;
+	utcDateTime=TDateTime(2005,month,30,23,45,55,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	//Prepare the service center time stamp
+	time.SetTime(expectedDecodedTime);
+
+	//Set offset=13, 3hrs15min
+	time.SetTimeOffset(13);
+
+	//Encode the PDU.
+	time.EncodeL(ptr);
+
+	//	This is the expected structure in bytes for the time above
+	semioctet = encodedPdu[0];			//2006
+	LOCAL_CHECKPOINT(semioctet==0x60);
+	semioctet = encodedPdu[1];			//Jan
+	LOCAL_CHECKPOINT(semioctet==0x10);
+	semioctet = encodedPdu[2];			//1st
+	LOCAL_CHECKPOINT(semioctet==0x10);
+	semioctet = encodedPdu[3];			//3h
+	LOCAL_CHECKPOINT(semioctet==0x30);
+	semioctet = encodedPdu[4];			//00min
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = encodedPdu[5];			//55sec
+	LOCAL_CHECKPOINT(semioctet==0x55);
+	semioctet = encodedPdu[6];			//offset = 13 x 15min bocks
+	LOCAL_CHECKPOINT(semioctet==0x31);
+
+	//---------------------------------------------------
+	//Check zero offset
+
+	//Expected UTC = 12/07/2005, 01h00, offset = 0hrs
+	//Local Time   = 12/07/2005, 01h00
+	encodedPdu.Delete(0,encodedPdu.MaxLength());
+	encodedPdu.SetLength(encodedPdu.MaxLength());
+	ptr = &encodedPdu[0];
+
+	month=EJuly;
+	utcDateTime=TDateTime(2005,month,11,1,0,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	//Prepare the service center time stamp
+	time.SetTime(expectedDecodedTime);
+
+	//Set offset=0
+	time.SetTimeOffset(0);
+
+	//Encode the PDU.
+	time.EncodeL(ptr);
+
+	//	This is the expected structure in bytes for the time above
+	semioctet = encodedPdu[0];			//2005
+	LOCAL_CHECKPOINT(semioctet==0x50);
+	semioctet = encodedPdu[1];			//July
+	LOCAL_CHECKPOINT(semioctet==0x70);
+	semioctet = encodedPdu[2];			//12th
+	LOCAL_CHECKPOINT(semioctet==0x21);
+	semioctet = encodedPdu[3];			//01h
+	LOCAL_CHECKPOINT(semioctet==0x10);
+	semioctet = encodedPdu[4];			//min
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = encodedPdu[5];			//sec
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = encodedPdu[6];			//offset
+	LOCAL_CHECKPOINT(semioctet==0x00);
+
+	//---------------------------------------------------
+	//Check boundary value, maximum positive
+
+	//Expected UTC = 12/07/2005, 01h00, offset = 19h45min
+	//Local Time   = 12/07/2005, 20h45
+	encodedPdu.Delete(0,encodedPdu.MaxLength());
+	encodedPdu.SetLength(encodedPdu.MaxLength());
+	ptr = &encodedPdu[0];
+
+	month=EJuly;
+	utcDateTime=TDateTime(2005,month,11,1,0,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	//Prepare the service center time stamp
+	time.SetTime(expectedDecodedTime);
+
+	//Set offset=0
+	time.SetTimeOffset(79);
+
+	//Encode the PDU.
+	time.EncodeL(ptr);
+
+	//	This is the expected structure in bytes for the time above
+	semioctet = encodedPdu[0];			//2005
+	LOCAL_CHECKPOINT(semioctet==0x50);
+	semioctet = encodedPdu[1];			//July
+	LOCAL_CHECKPOINT(semioctet==0x70);
+	semioctet = encodedPdu[2];			//12th
+	LOCAL_CHECKPOINT(semioctet==0x21);
+	semioctet = encodedPdu[3];			//20h
+	LOCAL_CHECKPOINT(semioctet==0x02);
+	semioctet = encodedPdu[4];			//45min
+	LOCAL_CHECKPOINT(semioctet==0x54);
+	semioctet = encodedPdu[5];			//sec
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = encodedPdu[6];			//offset
+	LOCAL_CHECKPOINT(semioctet==0x97);
+
+
+	//---------------------------------------------------
+	//Check boundary value, maximum positive
+
+	//Expected UTC = 12/07/2005, 01h00, offset = -19h45min
+	//Local Time   = 11/07/2005, 05h15
+	encodedPdu.Delete(0,encodedPdu.MaxLength());
+	encodedPdu.SetLength(encodedPdu.MaxLength());
+	ptr = &encodedPdu[0];
+
+	month=EJuly;
+	utcDateTime=TDateTime(2005,month,11,1,0,0,0);
+	expectedDecodedTime=TTime(utcDateTime);
+
+	//Prepare the service center time stamp
+	time.SetTime(expectedDecodedTime);
+
+	//Set offset=0
+	time.SetTimeOffset(-79);
+
+	//Encode the PDU.
+	time.EncodeL(ptr);
+
+	//	This is the expected structure in bytes for the time above
+	semioctet = encodedPdu[0];			//2005
+	LOCAL_CHECKPOINT(semioctet==0x50);
+	semioctet = encodedPdu[1];			//July
+	LOCAL_CHECKPOINT(semioctet==0x70);
+	semioctet = encodedPdu[2];			//11th
+	LOCAL_CHECKPOINT(semioctet==0x11);
+	semioctet = encodedPdu[3];			//05h
+	LOCAL_CHECKPOINT(semioctet==0x50);
+	semioctet = encodedPdu[4];			//15min
+	LOCAL_CHECKPOINT(semioctet==0x51);
+	semioctet = encodedPdu[5];			//sec
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = encodedPdu[6];			//offset
+	LOCAL_CHECKPOINT(semioctet==0x9F);
+	}
+
+/**
+ *  This is a unit test for class TSmsValidityPeriod.
+ *  TSmsValidityPeriod is not exported out of the gsmsu.dll.
+ *  We build gsmuelem.cpp to get access.
+ */
+EXPORT_C void CSmsStackTestUtils::CreateTSmsValidityPeriodL()
+	{
+	//Get the current UTC offset
+	TTime currUTCTime;
+	currUTCTime.UniversalTime();
+	TTimeIntervalSeconds currUTCOffset=User::UTCOffset();
+
+	//---------------------------------------------------
+	//Time()
+	//setup expected time for this validity period
+	//UTC = 2005/03/31 10hr45min55sec, offset=135sec
+	//Validity period = 3days
+	TMonth month=EMarch;
+	TDateTime utcDateTime(2005,month,30,10,45,55,0);
+	TTime utcTime(utcDateTime);
+	TInt offset=135;	// 135 seconds
+	TTimeIntervalSeconds utcOffset(offset);
+	User::SetUTCTimeAndOffset(utcTime,utcOffset);
+
+	//---------------------------------------------------
+	//Create
+	//Format is set to an absolute format
+	TSmsFirstOctet validityPeriodFormat=TSmsFirstOctet::ESmsVPFSemiOctet;
+	TSmsValidityPeriod validityPeriod(validityPeriodFormat);
+
+	//---------------------------------------------------
+	//Set the validity period
+	TInt expectedIntervalPeriod(3*24*60+15); // 3days15min=4320 minutes
+	TTimeIntervalMinutes validityTimeInterval(expectedIntervalPeriod);
+	validityPeriod.SetTimeIntervalMinutes(validityTimeInterval);
+	TTimeIntervalMinutes actualInterval=validityPeriod.TimeIntervalMinutes();
+	LOCAL_CHECKPOINT(expectedIntervalPeriod==actualInterval.Int());
+
+	//update utc, validity period is unchanged.
+	TDateTime nextDateTime(2005,month,30,12,45,55,0);
+	TTime nextTime(nextDateTime);
+	User::SetUTCTime(nextTime);
+
+	TTime actualValidityTime=validityPeriod.Time();
+	LOCAL_CHECKPOINT(actualValidityTime!=nextTime);
+
+	User::SetUTCTimeAndOffset(currUTCTime,currUTCOffset);
+	}
+
+/**
+ *  Test ability to encode a TSmsValidityPeriod inside a validity period inside a pdu
+ */
+EXPORT_C void CSmsStackTestUtils::EncodeTSmsValidityPeriodL()
+	{
+	//Get the current UTC offset
+	TTime currUTCTime;
+	currUTCTime.UniversalTime();
+	TTimeIntervalSeconds currUTCOffset=User::UTCOffset();
+
+	//Encode
+	const TInt KServiceCenterBuffSizeInPDU=7;			//Buffer is a 14 semi-octet buffer, 7 byte
+	TBuf8<KServiceCenterBuffSizeInPDU> serviceCenterBuffer;
+	serviceCenterBuffer.SetLength(serviceCenterBuffer.MaxLength());
+	TUint8* ptr = &serviceCenterBuffer[0];
+
+	//---------------------------------------------------
+	//Set the UTC time
+	//UTC 					= 03/03/2005, 12h00min30sec, offset = +3hrs = 10800 seconds
+	//Validity = 2hrs
+	//Expected local time 	= 03/03/2005, 17h00min30sec
+	TTimeIntervalSeconds utcOffset(10800);
+	TMonth month=EMarch;
+	TDateTime utcDateTime(2005,month,2,12,0,30,0);
+	TTime utcTime(utcDateTime);
+	User::SetUTCTimeAndOffset(utcTime,utcOffset);
+
+	//Create the validity period
+	TSmsFirstOctet validityPeriodFormat=TSmsFirstOctet::ESmsVPFSemiOctet;
+	TSmsValidityPeriod validityPeriod(validityPeriodFormat);
+
+	//Set the validity period to 2hrs, = 120 minutes
+	TInt expectedIntervalPeriod=120;
+	TTimeIntervalMinutes validityTimeInterval(expectedIntervalPeriod);
+	validityPeriod.SetTimeIntervalMinutes(validityTimeInterval);
+
+	//Encode the PDU.
+	validityPeriod.EncodeL(ptr);
+
+	//	This is the expected structure in bytes for the time above
+	TUint8 semioctet = serviceCenterBuffer[0];	//2005
+	LOCAL_CHECKPOINT(semioctet==0x50);
+	semioctet = serviceCenterBuffer[1];			//March
+	LOCAL_CHECKPOINT(semioctet==0x30);
+	semioctet = serviceCenterBuffer[2];			//3rd
+	LOCAL_CHECKPOINT(semioctet==0x30);
+	semioctet = serviceCenterBuffer[3];			//17h
+	LOCAL_CHECKPOINT(semioctet==0x71);
+	semioctet = serviceCenterBuffer[4];			//0min
+	LOCAL_CHECKPOINT(semioctet==0x00);
+	semioctet = serviceCenterBuffer[5];			//30sec
+	LOCAL_CHECKPOINT(semioctet>=2 && semioctet<=4);	// 1 second window each side of 3
+	semioctet = serviceCenterBuffer[6];			//offset
+	LOCAL_CHECKPOINT(semioctet==0x21);			//3hrs=15minx12
+
+	//Try a negative offset
+	//UTC 					= 03/03/2005, 12h00min30sec, offset = -6hrs = -21600 seconds
+	//Validity = 5days
+	//Expected local time 	= 08/03/2005, 06h00min30sec
+
+	utcOffset=TTimeIntervalSeconds(-21600);		// -6hrs validity
+	month=EMarch;
+	utcDateTime=TDateTime(2005,month,2,12,0,30,0);
+	utcTime=TTime(utcDateTime);
+	User::SetUTCTimeAndOffset(utcTime,utcOffset);
+
+	//Create the validity period
+	//validityPeriodFormat=TSmsFirstOctet::ESmsVPFSemiOctet;
+	//validityPeriod=TSmsValidityPeriod(validityPeriodFormat);
+
+	//Set the validity period to 5days, = 5*24*60=7200 minutes
+	expectedIntervalPeriod=7200;
+	validityTimeInterval=TTimeIntervalMinutes(expectedIntervalPeriod);
+	validityPeriod.SetTimeIntervalMinutes(validityTimeInterval);
+
+	//Encode the PDU
+	validityPeriod.EncodeL(ptr);
+
+	//	This is the expected structure in bytes for the time above
+	semioctet = serviceCenterBuffer[0];	//2005
+	LOCAL_CHECKPOINT(semioctet==0x50);
+	semioctet = serviceCenterBuffer[1];			//March
+	LOCAL_CHECKPOINT(semioctet==0x30);
+	semioctet = serviceCenterBuffer[2];			//3rd
+	LOCAL_CHECKPOINT(semioctet==0x80);
+	semioctet = serviceCenterBuffer[3];			//6h
+	LOCAL_CHECKPOINT(semioctet==0x60);
+	semioctet = serviceCenterBuffer[4];			//0min
+	LOCAL_CHECKPOINT(semioctet==0);
+	semioctet = serviceCenterBuffer[5];			//30sec
+	LOCAL_CHECKPOINT(semioctet>=2 && semioctet<=4);	// 1 second window each side of 3
+	semioctet = serviceCenterBuffer[6];			//offset
+	LOCAL_CHECKPOINT(semioctet==0x4A);		//-6hrs = -6*60=360 minutes 15x24 minutes
+
+	User::SetUTCTimeAndOffset(currUTCTime,currUTCOffset);
+	}
+
+/**
+ *  Test ability to decode a validity period inside a pdu into a TSmsValidityPeriod.
+ */
+EXPORT_C void CSmsStackTestUtils::DecodeTSmsValidityPeriodL()
+	{
+	//Get the current UTC offset
+	TTime currUTCTime;
+	currUTCTime.UniversalTime();
+	TTimeIntervalSeconds currUTCOffset=User::UTCOffset();
+
+	//Decode timestamp
+	const TInt KTimeStampSize=7;
+	//TInt ret=0;
+	TBuf8<KTimeStampSize> timeStamp;
+	timeStamp.SetLength(timeStamp.MaxLength());
+
+	//---------------------------------------------------
+	//	In integer values - local time
+	timeStamp[0]=64;		//year=2004
+	timeStamp[1]=32;		//month=Feb
+	timeStamp[2]=146;		//day=29th
+	timeStamp[3]=81;		//hour=15h
+	timeStamp[4]=3;			//minute=30min
+	timeStamp[5]=0;			//second=0
+	timeStamp[6]=33;		//timeZone=12x15min=3hrs
+
+	//UTC time is 29 January 2004, 12.30
+	//This should give a TTimeIntervalMinutes of 31 Days = 44640 minutes
+	TMonth month=EJanuary;
+	TDateTime utcDateTime(2004,month,28,12,30,0,0);
+	//Setup UTC time and offset
+	TTime utcTime(utcDateTime);
+	//+3hrs offset = 10800 seconds
+	TTimeIntervalSeconds utcOffset(10800);
+	User::SetUTCTimeAndOffset(utcTime,utcOffset);
+
+	//Create buffer
+	TGsmuLex8 timeStampPosOffsetBuffer(timeStamp);
+	//Create validity period
+	TSmsFirstOctet validityPeriodFormat=TSmsFirstOctet::ESmsVPFSemiOctet;
+	TSmsValidityPeriod validityPeriod(validityPeriodFormat);
+
+	//Decode
+	validityPeriod.DecodeL(timeStampPosOffsetBuffer);
+
+	//Now I have a TValidityPeriod
+	//Check validity period format
+	//ValidityPeriodFormat
+	LOCAL_CHECKPOINT(validityPeriod.ValidityPeriodFormat()==TSmsFirstOctet::ESmsVPFSemiOctet);
+
+	//Check the expected Interval
+	TTimeIntervalMinutes expectedInterval(44640);
+	//Give or take a minute
+	TTimeIntervalMinutes actualInterval=validityPeriod.TimeIntervalMinutes();
+	LOCAL_CHECKPOINT(actualInterval.Int()==expectedInterval.Int()+1||actualInterval.Int()==expectedInterval.Int()-1||actualInterval.Int()==expectedInterval.Int());
+	User::SetUTCTimeAndOffset(currUTCTime,currUTCOffset);
+	}
+
+
+EXPORT_C void CSmsStackTestUtils::AppendUserDataL(TGsmSms& aPdu, const CSmsUserData& aUD, TInt aUDL /* = KErrNotFound */)
+/**
+ *  Appends an encoded CSmsUserData to the PDU
+ *  
+ *  @pre aPdu contains an appropriate Data Coding Scheme
+ *  @param aPdu Partially constructed TGsmSms, lacking the user data
+ *  @param aUD The User Data to append to aPdu
+ *  @param aUDL OPTIONAL Value to set the TP-UDL in the PDU. Only used if >= 0
+ */
+	{
+	RMobileSmsMessaging::TMobileSmsGsmTpdu pdu(aPdu.Pdu());
+	const TInt origLen = pdu.Length();
+	pdu.SetLength(pdu.MaxLength());
+	TUint8* ptr0 = &pdu[origLen];
+	TUint8* ptr1 = ptr0;
+
+	ptr1 = aUD.EncodeL(ptr1);
+
+	if (aUDL >= 0 && aUDL <= 0x99)
+		{
+		*ptr0 = static_cast<TInt8>(aUDL);
+		}
+
+	pdu.SetLength((ptr1 - ptr0) + origLen);
+	aPdu.SetPdu(pdu);
+	}
+
+EXPORT_C void CSmsStackTestUtils::CompareDCSL(const CSmsPDU& aPdu, TSmsDataCodingScheme aDCS)
+/**
+ *  TODO
+ */
+	{
+	LOCAL_CHECKPOINT(aPdu.DataCodingSchemePresent());
+	LOCAL_CHECKPOINT(aPdu.Alphabet() == aDCS.Alphabet());
+	LOCAL_CHECKPOINT(aPdu.Bits7To4() == aDCS.Bits7To4());
+
+	TSmsDataCodingScheme::TSmsClass class1, class2;
+	const TBool hasClass1 = aPdu.Class(class1);
+	const TBool hasClass2 = aPdu.Class(class2);
+
+	LOCAL_CHECKPOINT((hasClass1 && hasClass2) || (!hasClass1 && !hasClass2));
+
+	if (hasClass1)
+		{
+		LOCAL_CHECKPOINT(class1 == class2);
+		}
+	}
+
+EXPORT_C void CSmsStackTestUtils::ComparePIDL(const CSmsPDU& aPDU, TSmsProtocolIdentifier aPID)
+/**
+ *  TODO
+ */
+	{
+	LOCAL_CHECKPOINT(aPDU.ProtocolIdentifierPresent());
+	LOCAL_CHECKPOINT(aPDU.PIDType() == aPID.PIDType());
+	LOCAL_CHECKPOINT(aPDU.TelematicDeviceIndicator() == aPID.TelematicDeviceIndicator());
+
+	if (aPDU.TelematicDeviceIndicator()==TSmsProtocolIdentifier::ESmsTelematicDevice)
+		{
+		LOCAL_CHECKPOINT(aPDU.TelematicDeviceType() == aPID.TelematicDeviceType());
+		}
+	}
+
+EXPORT_C void CSmsStackTestUtils::CompareUDL(const CSmsPDU& aPDU, const CSmsUserData& aUD)
+/**
+ *  TODO
+ */
+	{
+	LOCAL_CHECKPOINT(aPDU.UserDataPresent());
+	const CSmsUserData& pduUD = aPDU.UserData();
+
+	TInt count = pduUD.NumInformationElements();
+
+	LOCAL_CHECKPOINT(count == aUD.NumInformationElements());
+
+	while (count--)
+		{
+		const CSmsInformationElement& ie1 = pduUD.InformationElement(count);
+		const CSmsInformationElement& ie2 = aUD.InformationElement(count);
+		LOCAL_CHECKPOINT(ie1.Identifier() == ie2.Identifier());
+		LOCAL_CHECKPOINT(ie1.Data() == ie2.Data());
+		}
+
+	LOCAL_CHECKPOINT(pduUD.Body() == aUD.Body());
+	}
+
+EXPORT_C void CSmsStackTestUtils::PrintAndTestDecodeL(const TGsmSms& aPdu, TSmsDataCodingScheme aExpectedDCS, TSmsProtocolIdentifier aExpectedPID, const CSmsUserData& aExpectedUD, TBool aIsMobileTerminated, TInt aExpectedError)
+/**
+ *  TODO
+ */
+	{
+	LOGSMSIFPDU(_L8("TestPduDbToolsL PDU: "), aPdu.Pdu(), EFalse);
+	LOGSMSIFTIMESTAMP();
+
+	CSmsPDU* pdu = NULL;
+	TRAPD(err, pdu = CSmsPDU::NewL(aPdu, *iCharConv, iFs, aIsMobileTerminated));
+
+	if (err == KErrNone)
+		CleanupStack::PushL(pdu);
+
+	LOCAL_CHECKPOINT(err == aExpectedError);
+
+	if (err == KErrNone)
+		{
+		CompareDCSL(*pdu, aExpectedDCS);
+		ComparePIDL(*pdu, aExpectedPID);
+		CompareUDL(*pdu, aExpectedUD);
+		}
+
+	if (err == KErrNone)
+		CleanupStack::PopAndDestroy(pdu);
+	}
+
+EXPORT_C TInt CSmsStackTestUtils::StoreParamsL(CMobilePhoneSmspList& aSmspList, RSocket& aSocket, TBool aCancelAfterRequest)
+/**
+ *  Stream Sms parameters out to the socket server
+ *  @param aSmspList has Sms parameters list that is streamed to the socket server
+ *  @param aSocket is used to stream the aSmspList to the socket server
+ *  @param aCancelAfterRequest Boolean parameter tells if the request is wanted to be canceled
+ *  @return TInt : The completing status of the request
+ */
+	{
+	// Write parameters
+	RSmsSocketWriteStream writestream(aSocket);
+	TRAPD(ret,writestream << aSmspList);
+	LOCAL_CHECKPOINT(ret == KErrNone);
+	TRAP(ret,writestream.CommitL());
+	LOCAL_CHECKPOINT(ret == KErrNone);
+
+	TRequestStatus status;
+	aSocket.Ioctl(KIoctlWriteSmsParams,status,NULL, KSolSmsProv);
+    if(aCancelAfterRequest)
+        aSocket.CancelIoctl();
+	User::WaitForRequest(status);
+
+	PRINTF2(_L("StoreParamsL - storeSmsParams returned %d"), status.Int());
+	return status.Int();
+	}
+
+EXPORT_C TInt CSmsStackTestUtils::RetrieveParamsL(CMobilePhoneSmspList& aSmspList, RSocket& aSocket, TBool aCancelAfterRequest)
+/**
+ *  Retrieve Sms parameters
+ *  @param aSmspList pointer to the Sms parameters list to be read into
+ *  @param aSocket is used to stream the aSmspList from the socket server
+ *  @param aCancelAfterRequest Boolean parameter tells if the request is wanted to be canceled
+ *  @return TInt : The completing status of the request
+ */
+	{
+	TInt ret;
+	TRequestStatus status;
+
+	//
+	// Retrieve Sms parameters from Phone
+	//
+	aSocket.Ioctl(KIoctlReadSmsParams,status,NULL, KSolSmsProv);
+    if(aCancelAfterRequest)
+        aSocket.CancelIoctl();
+	User::WaitForRequest(status);
+
+    if(status.Int() == KErrNone && !aCancelAfterRequest)
+        {
+	    RSmsSocketReadStream readstream(aSocket);
+	    TRAP(ret,readstream >> aSmspList);
+	    LOCAL_CHECKPOINT(ret == KErrNone);
+        }
+
+    return status.Int();
+	}
+
+EXPORT_C void CSmsStackTestUtils::MakeParametersReadRequestL(RSocket& aSocket)
+/**
+ *  Make SMS parameters read request to the SMS Stack.
+ *  @param aSocket that is used to make request to the stack.
+ */
+	{
+	TRequestStatus status;
+
+    // Make read SMS params request to the SMS Stack
+    aSocket.Ioctl(KIoctlReadSmsParams,status,NULL, KSolSmsProv);
+    User::WaitForRequest(status);
+	PRINTF2(_L("Retrieve SMS parameters returned %d"), status.Int());
+	if(status.Int() != KErrNone)
+		{
+		User::Leave(status.Int());
+		}
+	}
+
+EXPORT_C void CSmsStackTestUtils::StoreParamsLeaveIfErrorL(CMobilePhoneSmspList& aSmspList,RSocket& aSocket)
+/**
+ *  Stream Sms parameters out to the socket server and make request.
+ *  @param aSmspList has Sms parameters list that is streamed to the socket server
+ *  @param aSocket is used to stream the aSmspList to the socket server
+ */
+	{
+	// Write parameters
+	RSmsSocketWriteStream writestream(aSocket);
+	writestream << aSmspList;
+	writestream.CommitL();
+
+	TRequestStatus status;
+	aSocket.Ioctl(KIoctlWriteSmsParams,status,NULL, KSolSmsProv);
+	User::WaitForRequest(status);
+	PRINTF2(_L("Store SMS parameters returned %d"), status.Int());
+	if(status.Int() != KErrNone)
+		{
+		User::Leave(status.Int());
+		}
+	}
+
+EXPORT_C TInt CSmsStackTestUtils::TestParameters(CMobilePhoneSmspList& aLeft,CMobilePhoneSmspList& aRight)
+/**
+ *  Compare sms parameters taken from chunk to parameters retrieved from SIM
+ *  @param aLeft sms parameters taken from the Dummychunk
+ *  @param aRight sms parameters retrieved from the SIM
+ *  @return TInt : The error code
+ */
+	{
+    TInt ret(KErrNone);
+
+    if(aLeft.Enumerate() == aRight.Enumerate())
+        {
+        for(TInt storeIndex=0; storeIndex<aLeft.Enumerate(); storeIndex++)
+            {
+            const RMobileSmsMessaging::TMobileSmspEntryV1*  leftEntry(NULL);
+            TBool found=EFalse;
+
+            TRAPD(myLeftErr, leftEntry = &aLeft.GetEntryL(storeIndex));
+            if (myLeftErr != KErrNone)
+            	{
+            	return myLeftErr;
+            	}
+            if (leftEntry == NULL)
+            	{
+            	return KErrArgument;
+            	}
+
+            for(TInt writeIndex=0; writeIndex<aRight.Enumerate(); writeIndex++)
+                {
+                const RMobileSmsMessaging::TMobileSmspEntryV1*  rightEntry(NULL);
+                
+                TRAPD(myRightErr, rightEntry = &aRight.GetEntryL(writeIndex));
+	            if (myRightErr != KErrNone)
+	            	{
+	            	return myRightErr;
+	            	}
+	            if (rightEntry == NULL)
+	            	{
+	            	return KErrArgument;
+	            	}
+
+                if(leftEntry->iIndex == rightEntry->iIndex)
+                    {
+                    found=ETrue;
+					if((leftEntry->iValidParams != rightEntry->iValidParams) ||
+						(leftEntry->iText != rightEntry->iText))
+						{
+						ret = KErrCorrupt;
+						break;
+						}
+					if(leftEntry->iValidParams & RMobileSmsMessaging::KDestinationIncluded)
+						{
+						ret = TestPhoneNumbers(leftEntry->iDestination,rightEntry->iDestination);
+						if(ret)
+							break;
+						}
+					if(leftEntry->iValidParams & RMobileSmsMessaging::KSCAIncluded)
+						{
+						ret = TestPhoneNumbers(leftEntry->iServiceCentre,rightEntry->iServiceCentre);
+						if(ret)
+							break;
+						}
+					if((leftEntry->iValidParams & RMobileSmsMessaging::KProtocolIdIncluded) &&
+						(leftEntry->iProtocolId != rightEntry->iProtocolId))
+						ret = KErrCorrupt;
+					if((leftEntry->iValidParams & RMobileSmsMessaging::KValidityPeriodIncluded) &&
+						(leftEntry->iValidityPeriod != rightEntry->iValidityPeriod))
+						ret = KErrCorrupt;
+					if((leftEntry->iValidParams & RMobileSmsMessaging::KDcsIncluded) &&
+						(leftEntry->iDcs != rightEntry->iDcs))
+						ret = KErrCorrupt;
+                    break;
+                    }
+                }
+
+            if(!found || ret != KErrNone)
+                {
+                ret = KErrCorrupt;
+                break;
+                }
+            }
+        }
+    else
+        ret = KErrCorrupt;
+
+    if(ret == KErrNone)
+		PRINTF1(_L("SMS Parameters Ok!") );
+    else
+		PRINTF2(_L("ERROR: SMSP lists doesn't match: %d"), ret );
+
+    return ret;
+	}
+
+EXPORT_C TInt CSmsStackTestUtils::TestPhoneNumbers(const RMobilePhone::TMobileAddress& aLeftNumber,const RMobilePhone::TMobileAddress& aRightNumber)
+/**
+ *  Compare phone numbers
+ *  @param aLeftNumber reference to TMobileAddress object
+ *  @param aRightNumber reference to TMobileAddress object
+ */
+	{
+	TInt ret(KErrNone);
+	TBuf<TGsmSmsTelNumberMaxLen> leftNumber;
+	TBuf<TGsmSmsTelNumberMaxLen> rightNumber;
+
+	//Take '+' sign away first
+	leftNumber.Copy(aLeftNumber.iTelNumber);
+	if(leftNumber.Length() > 0 && leftNumber[0] == '+')
+		{
+		// Remove "+" sign from telephony number
+		leftNumber.Delete(0,1);
+		leftNumber.Trim();
+		}
+	//Take '+' sign away first
+	rightNumber.Copy(aRightNumber.iTelNumber);
+	if(rightNumber.Length() > 0 && rightNumber[0] == '+')
+		{
+		// Remove "+" sign from telephony number
+		rightNumber.Delete(0,1);
+		rightNumber.Trim();
+		}
+	if((leftNumber.Compare(rightNumber) != 0) ||
+       (aLeftNumber.iTypeOfNumber != aRightNumber.iTypeOfNumber) ||
+       (aLeftNumber.iNumberPlan != aRightNumber.iNumberPlan))
+		{
+        ret = KErrCorrupt;
+        }
+	return(ret);
+	}
+
+EXPORT_C void CSmsStackTestUtils::PrintSmspEntry(RMobileSmsMessaging::TMobileSmspEntryV1& aEntryToTsy)
+/**
+ *  Print a single SMS parameter entry, induvidual content depends on valid flags
+ *  @param aEntryToTsy reference to TMobileSmspEntryV1 object
+ */
+    {
+    PRINTF2( _L("Index %d"), aEntryToTsy.iIndex);
+    PRINTF2( _L("Text %S"),  &aEntryToTsy.iText);
+    PRINTF2( _L("Validity Flags %d"), aEntryToTsy.iValidParams);
+
+    // Protocol ID
+    if (aEntryToTsy.iValidParams & RMobileSmsMessaging::KProtocolIdIncluded)
+        {
+        PRINTF2( _L("Protocol ID is %d"),
+                                    aEntryToTsy.iProtocolId);
+        }
+
+    //DCS
+    if (aEntryToTsy.iValidParams & RMobileSmsMessaging::KDcsIncluded)
+        {
+        PRINTF2( _L("Default Ccding Scheme is %d"),
+                                    aEntryToTsy.iDcs);
+        }
+
+   //validity
+    if (aEntryToTsy.iValidParams & RMobileSmsMessaging::KValidityPeriodIncluded)
+        {
+        PRINTF2( _L("Validity Period is %d"),
+                                    aEntryToTsy.iValidityPeriod);
+        }
+
+    // destination number
+    if (aEntryToTsy.iValidParams & RMobileSmsMessaging::KDestinationIncluded)
+        {
+        PRINTF2( _L("Destination Type Number is %d"),
+                                    aEntryToTsy.iDestination.iTypeOfNumber);
+        PRINTF2( _L("Destination Number Plan is %d"),
+                                    aEntryToTsy.iDestination.iNumberPlan);
+        PRINTF2( _L("Destination Number is %S"),
+                                    &aEntryToTsy.iDestination.iTelNumber);
+        }
+    // service center number
+    if (aEntryToTsy.iValidParams & RMobileSmsMessaging::KSCAIncluded)
+        {
+        PRINTF2( _L("Service Center Type Number is %d"),
+                                    aEntryToTsy.iServiceCentre.iTypeOfNumber);
+        PRINTF2( _L("Service Center Number Plan is %d"),
+                                    aEntryToTsy.iServiceCentre.iNumberPlan);
+        PRINTF2( _L("Service Center Number is %S"),
+                                    &aEntryToTsy.iServiceCentre.iTelNumber);
+        }
+    }
+
+EXPORT_C void CSmsStackTestUtils::PrintSmspList(CMobilePhoneSmspList& aSmspList)
+/**
+ *  Print a SMS parameter list
+ *  @param aSmspList reference to CMobilePhoneSmspList object
+ */
+    {
+    TInt entries;
+    entries = aSmspList.Enumerate();
+
+    if (entries != 1)
+        {
+        PRINTF2(_L("The Sms Parameter List has %d parameter entries "), entries );
+        }
+    else
+        {
+        PRINTF2(_L("The Sms Parameter List has %d parameter entry "), entries );
+        }
+
+    RMobileSmsMessaging::TMobileSmspEntryV1 entryToTsy;
+
+    for (TInt i = 0; i < entries; i++)
+        {
+        PRINTF1(_L(""));
+        TRAPD(err, entryToTsy = aSmspList.GetEntryL(i));
+
+        if (err == KErrNone)
+            {
+            PrintSmspEntry(entryToTsy);
+            }
+        else
+            {
+            //if leave occurs print to the console
+            PRINTF2(_L("SmspList.GetEntryL() left: possible cause memory allocation %d"), err);
+            break;
+            }
+        }
+    }
+
+
+
+
+//
+//             CTestGetSmsList
+//
+
+EXPORT_C CTestGetSmsList* CTestGetSmsList::NewL(TInt aPriority, RSocketServ& aSocketServer, CSmsStackTestUtils& aTestUtils)
+	{
+	CTestGetSmsList* smsListGetter = new(ELeave) CTestGetSmsList(aPriority, aSocketServer, aTestUtils);
+	CleanupStack::PushL(smsListGetter);
+	smsListGetter->ConstructL();
+	CleanupStack::Pop(smsListGetter);
+	return smsListGetter;
+	}
+
+CTestGetSmsList::CTestGetSmsList(TInt aPriority, RSocketServ& aSocketServer, CSmsStackTestUtils& aTestUtils)
+/**
+ *  Constructor
+ *  
+ *   *
+ */
+: CSmsuActiveBase(aPriority), //parent construction
+iSocketServer(aSocketServer),
+iTestUtils(aTestUtils)
+	{
+	}
+
+
+void CTestGetSmsList::ConstructL()
+	{
+	iTestUtils.OpenSmsSocketLC(iSocketServer,iSocket,ESmsAddrLocalOperation);
+	CleanupStack::Pop(&iSocket);
+	}
+
+EXPORT_C void CTestGetSmsList::GetSmsList(TRequestStatus& aStatus)
+/**
+ *  Starts the active object: Puts a Ioctl request on a socket to enumerate the number
+ *  of messsages in the store
+ *  @param	aStatus, copied to iStatus of this active object
+ *  
+ *   *
+ */
+	{
+	Queue(aStatus);
+	iMessageCount()=0;
+	iSocket.Ioctl(KIoctlEnumerateSmsMessages, iStatus,&iMessageCount, KSolSmsProv);
+	SetActive();
+	iState = EEnuming;
+	}
+
+void CTestGetSmsList::DoRunL()
+/**
+ *  Active object completion function
+ *  Active while there are still messages to read from the socket
+ */
+	{
+	iTestUtils.PRINTF1(_L("Messages enumerated"));
+	User::LeaveIfError(iStatus.Int());
+
+	switch (iState)
+		{
+		case EEnuming:
+			{
+			iRemainingMessages = iMessageCount();
+			iTestUtils.PRINTF2(_L("%d messages in the store"), iRemainingMessages);
+			}
+
+		case EReading:
+			{
+			if (iRemainingMessages > 0)
+				{
+				iRemainingMessages--;
+				CSmsBuffer* buffer=CSmsBuffer::NewL();
+				CSmsMessage* smsMessage=CSmsMessage::NewL(iTestUtils.iFs, CSmsPDU::ESmsDeliver,buffer);
+				CleanupStack::PushL(smsMessage);
+
+				RSmsSocketReadStream readstream(iSocket);
+				readstream >> *smsMessage;
+				CleanupStack::PopAndDestroy(smsMessage);//operation was done only to clear the socket, we are not interested in the message content
+
+				iSocket.Ioctl(KIoctlReadMessageSucceeded, iStatus, NULL, KSolSmsProv);
+				SetActive();
+				iState = EReading;
+				}
+			}
+		}
+	}
+
+void CTestGetSmsList::DoCancel()
+	{
+	iSocket.CancelIoctl();
+	Complete(KErrCancel);
+	}
+
+
+//
+//         SmsReceiver AO
+//
+
+EXPORT_C CTestReceiveMessages* CTestReceiveMessages::NewL(TInt aPriority, RSocketServ& aSocketServer, CSmsStackTestUtils& aTestUtils)
+	{
+	CTestReceiveMessages* smsReceiver = new(ELeave) CTestReceiveMessages(aPriority, aSocketServer, aTestUtils);
+	CleanupStack::PushL(smsReceiver);
+	smsReceiver->ConstructL();
+	CleanupStack::Pop(smsReceiver);
+	return smsReceiver;
+	}
+
+CTestReceiveMessages::CTestReceiveMessages(TInt aPriority, RSocketServ& aSocketServer, CSmsStackTestUtils& aTestUtils)
+/**
+ *  Constructor
+ */
+: CSmsuActiveBase(aPriority), //parent construction
+iSocketServer(aSocketServer),
+iTestUtils(aTestUtils)
+	{
+	}
+
+
+void CTestReceiveMessages::ConstructL()
+	{
+	iTestUtils.OpenSmsSocketLC(iSocketServer,iSocket,ESmsAddrRecvAny);
+	CleanupStack::Pop(&iSocket);
+	}
+
+EXPORT_C void CTestReceiveMessages::Receive(TRequestStatus& aStatus, TInt aNumberOfMessages)
+/**
+ *  Starts the AO by putting a request on the socket receive sms messages
+ *  This function will normally be used when we start using the active object
+ *  Active while the number of received messages is > aNumberOfmessages
+ *  @param aNumberOfMessages the number of messages to be received
+ */
+	{
+	Queue(aStatus);
+	if (iNumberOfReceivedMessages >= aNumberOfMessages)
+		Complete(KErrNone);
+	else
+		{
+		iNumberOfMessagesToReceive=aNumberOfMessages;
+		if (!IsActive())
+			Receive();
+		}
+	}
+
+EXPORT_C void CTestReceiveMessages::Receive()
+/**
+ *  Reposts the receive request -note Receive(aStatus, aNunmberOfMessages) has to be called prior to this one
+ *  
+ */
+	{
+	iMessageBuf()=KSockSelectRead;
+	iSocket.Ioctl(KIOctlSelect,iStatus,&iMessageBuf,KSOLSocket);
+	iState = EReceiving;
+	SetActive();
+	}
+
+
+void CTestReceiveMessages::DoRunL()
+/**
+ *  Active object completion function.completes once in each state for each message received
+ *  
+ */
+	{
+	User::LeaveIfError(iStatus.Int());
+
+	switch(iState)
+		{
+		case (EReceiving):
+			{
+			iTestUtils.PRINTF1(_L(" Message received"));
+
+			CSmsBuffer* buffer=CSmsBuffer::NewL();
+			CSmsMessage* smsMessage=CSmsMessage::NewL(iTestUtils.iFs, CSmsPDU::ESmsSubmit,buffer);
+			CleanupStack::PushL(smsMessage);
+			RSmsSocketReadStream readstream(iSocket);
+			readstream >> *smsMessage;
+			CleanupStack::PopAndDestroy(smsMessage);//operation was done only to clear the socket, we are not interested in the message content
+			iSocket.Ioctl(KIoctlReadMessageSucceeded, iStatus, NULL, KSolSmsProv);
+			SetActive();
+			iState = EReceived;
+			break;
+			}
+		case (EReceived):
+			{
+			iNumberOfReceivedMessages++;
+			iTestUtils.PRINTF2(_L("%d Messages received"), iNumberOfReceivedMessages);
+			iState=EReceiving;
+
+			if (iNumberOfMessagesToReceive!=iNumberOfReceivedMessages || iReport == NULL)
+				Receive();
+
+			break;
+			}
+		}
+	}
+
+void CTestReceiveMessages::DoCancel()
+	{
+	iSocket.CancelIoctl();
+	Complete(KErrCancel);
+	}
+
+
+TInt CTestReceiveMessages::NumberReceived()
+/**
+ *  Returns the number of received sms messages
+ */
+	{
+	return iNumberOfReceivedMessages;
+	}
+
+//
+//         SmsReceiverEnumerator wrapping AO
+//
+
+
+EXPORT_C CTestReceiveEnumerateMessages* CTestReceiveEnumerateMessages::NewL(TInt aPriority, RSocketServ& aSocketServer, CSmsStackTestUtils& aTestUtils)
+	{
+	CTestReceiveEnumerateMessages* smsReceiverEnumerator = new(ELeave) CTestReceiveEnumerateMessages(aPriority, aSocketServer, aTestUtils);
+	CleanupStack::PushL(smsReceiverEnumerator);
+	smsReceiverEnumerator->ConstructL();
+	CleanupStack::Pop(smsReceiverEnumerator);
+	return smsReceiverEnumerator;
+	}
+
+CTestReceiveEnumerateMessages::CTestReceiveEnumerateMessages(TInt aPriority, RSocketServ& aSocketServer, CSmsStackTestUtils& aTestUtils)
+/**
+ *  Constructor
+ *   *
+ */
+: CSmsuActiveBase(aPriority), //parent construction
+iSocketServer(aSocketServer),
+iTestUtils(aTestUtils)
+	{
+	}
+
+
+void CTestReceiveEnumerateMessages::ConstructL()
+	{
+	iEnumerator = CTestGetSmsList::NewL(KActiveObjectPriority, iSocketServer, iTestUtils);
+	iReceiver = CTestReceiveMessages::NewL(KActiveObjectPriority, iSocketServer, iTestUtils);
+	ConstructTimeoutL();
+	}
+
+EXPORT_C void CTestReceiveEnumerateMessages::Start(TInt aEnumExpected, TInt aRecvExpected, TInt aRecvInitial)
+/**
+ *  Starts the active object state machine in order to have the following
+ *  -receive iRecvExpected messages
+ *  -Enumerate messages in store and verify there are iEnumExpected and continue receiving
+ *  -Receive the rest of the messages (iRecvExpected in total)
+ *  -Request to receive another message that should time out as only 5 messages are received
+ *  -Flag error if that last message is received
+ */
+	{
+	iEnumExpected=aEnumExpected;
+	iRecvExpected=aRecvExpected;
+	iRecvInitial=aRecvInitial;
+
+	iReceiver->Receive(iStatus, aRecvInitial);
+	iState = ERecvInitial;
+	SetActive();
+	CActiveScheduler::Start();
+	}
+
+void CTestReceiveEnumerateMessages::Complete(TInt aErr)
+	{
+	iStatus=aErr;
+	CActiveScheduler::Stop();
+	}
+
+void CTestReceiveEnumerateMessages::DoRunL()
+	{
+	User::LeaveIfError(iStatus.Int());
+
+	switch(iState)
+		{
+		case ERecvInitial:
+			{
+			iEnumerator->GetSmsList(iStatus);
+			iReceiver->Receive();
+			iState=EEnumerating;
+			SetActive();
+			break;
+			}
+		case EEnumerating:
+			{
+			if(iEnumerator->iMessageCount()==TUint(iEnumExpected))
+				iTestUtils.PRINTF1(_L("**enumerated the right number of messages"));
+			else
+				User::Leave(KErrCorrupt);
+			iReceiver->Receive(iStatus, 5);
+			SetActive();
+			iState=ESecondReceiving;
+			break;
+			}
+		case ESecondReceiving:
+			{
+			iReceiver->Receive(iStatus, 1 + iRecvExpected);
+			iState=ETryingToReceiveOneMore;
+			TimedSetActive(15000000);
+			break;
+			}
+
+		case ETryingToReceiveOneMore:
+			{
+			User::Leave(KErrOverflow);
+			break;
+			}
+
+		}
+
+	}
+
+void CTestReceiveEnumerateMessages::DoCancel()
+/**
+ *  Calls cancel on the active objects this owns
+ *  
+ */
+	{
+	TimedSetActiveCancel();
+	TInt err = KErrCancel;
+
+	switch(iState)
+		{
+		case ERecvInitial:
+			iReceiver->Cancel();
+			break;
+		case EEnumerating:
+			iEnumerator->Cancel();
+			break;
+		case ESecondReceiving:
+
+			iReceiver->Cancel();
+			break;
+
+		case ETryingToReceiveOneMore:
+
+			iReceiver->Cancel();
+
+			if (TimedOut())
+				err = KErrNone;
+
+			break;
+		}
+
+	Complete(err);
+	}
+
+
+EXPORT_C CTestReceiveEnumerateMessages::~CTestReceiveEnumerateMessages()
+/**
+ *  destructor
+ */
+ 	{
+	delete iReceiver;
+	delete iEnumerator;
+	}