// 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 "smsstacktestutilities.h"
#include <commsdattypesv1_1.h>
#include <commsdattypesv1_1_internal.h>
#include <logcli.h>
#include <e32math.h>
#include <e32test.h>
#include <f32file.h>
#include <logwraplimits.h>
#include "smsustrm.h"
#include "Gsmumsg.h"
#include "smsuaddr.H"
#include "gsmubuf.h"
#include "smspdudb.h"
#include "SmsuTimer.h"
#include "smsstacklog.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::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);
TProtocolDesc desc;
aSocket.Info(desc);
PRINTF2(_L("Protocol name: %S"), &desc.iName);
TTimeIntervalMicroSeconds32 InitPause=9000000; //Required Pause to Allow SMSStack to Complete its Async Init
User::After(InitPause); //call to the TSY and finish its StartUp.
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(2, testActive); // testActive, logWrapper
}
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 - default values
config.iMaxEventAge = 2592000;
config.iMaxLogSize = 1000;
config.iMaxRecentLogSize = 20;
testActive->StartL();
logClient.ChangeConfig(config, testActive->iStatus);
CActiveScheduler::Start();
LOCAL_CHECKPOINT(testActive->iStatus.Int() == KErrNone);
CleanupStack::PopAndDestroy(2, testActive); // testActive, logWrapper
}
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); // 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);
PRINTF2(_L("iStatus is %d"), testActive->iStatus.Int());
logWrapper->Log().AddEvent(*logevent,testActive->iStatus);
CActiveScheduler::Start();
PRINTF2(_L("iStatus is %d"), testActive->iStatus.Int());
LOCAL_CHECKPOINT(testActive->iStatus.Int() == KErrNone);
id=logevent->Id();
CleanupStack::PopAndDestroy(logevent);
}
CleanupStack::PopAndDestroy(2, testActive); // 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(3, pduBuf); // smsTx, sc, pduBuf
}
CleanupStack::PopAndDestroy(2, pdus); // pdus, submitReport
}
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;
}
EXPORT_C CTestGetSmsList::CTestGetSmsList(TInt aPriority, RSocketServ& aSocketServer, CSmsStackTestUtils& aTestUtils)
: 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;
}