--- /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;
+ }