diff -r 000000000000 -r 3553901f7fa8 smsprotocols/smsstack/test/smsstacktestutilities.cpp --- /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 +#include + +#include "smsstacktestutilities.h" +#include +#include "smsustrm.h" +#include "Gsmumsg.h" +#include "smsuaddr.H" +#include "gsmubuf.h" + +#include "smspdudb.h" +#include +#include +#include "SmsuTimer.h" +#include "smsstacklog.h" +#include + +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* globalSettingsField = new(ELeave) CMDBField(KCDTIdModemPhoneServicesSMS); + CleanupStack::PushL(globalSettingsField); + globalSettingsField->SetRecordId(1); + globalSettingsField->LoadL(*db); + modemId = *globalSettingsField; + CleanupStack::PopAndDestroy(globalSettingsField); + + CMDBField* tsyField = new(ELeave) CMDBField(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 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* smsBearerField = new(ELeave) CMDBField(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 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 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(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(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 (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 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 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* 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* pdus = EncodeMessageLC(aMessage); + + HBufC8* submitReport = NULL; + + if (aSubmitReport == NULL) + { + submitReport = KNullDesC8().AllocLC(); + } + else + { + CArrayFixFlat* 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* CSmsStackTestUtils::EncodeMessageLC(CSmsMessage& aMessage) const + { + CArrayFixFlat* array = new (ELeave) CArrayFixFlat(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 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 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 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 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(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; storeIndexiIndex == 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 leftNumber; + TBuf 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; + }