// Copyright (c) 2007-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:
// Runs the actual multiple test step
//
// LBS includes.
#include <lbs/lbsnetprotocolbase.h>
#include <lbs/lbsassistancedatabuilderset.h>
// LBS test includes.
#include "ctlbshybridmultipletest.h"
#include <lbs/test/tlbsutils.h>
#include "argutils.h"
#include <lbs/test/activeyield.h>
/**
Static Constructor
*/
CT_LbsHybridMultipleTest* CT_LbsHybridMultipleTest::New(CT_LbsHybridMultipleServer& aParent)
{
// Note that we do not use ELeave.
// This means that having insufficient memory will return NULL;
CT_LbsHybridMultipleTest* testStep = new CT_LbsHybridMultipleTest(aParent);
if (testStep)
{
TInt err = KErrNone;
TRAP(err, testStep->ConstructL());
if (err)
{
delete testStep;
testStep = NULL;
}
}
return testStep;
}
/**
* Constructor
*/
CT_LbsHybridMultipleTest::CT_LbsHybridMultipleTest(CT_LbsHybridMultipleServer& aParent) : CT_LbsHybridMultipleStep(aParent),
iCheckForNewSequencesToStart(ETrue)
{
SetTestStepName(KLbsHybridMultipleTest);
}
void CT_LbsHybridMultipleTest::ConstructL()
{
// Create the base class objects.
CT_LbsHybridMultipleStep::ConstructL();
iController = CLbsPrivacyController::NewL(*this);
iCheckNewSequenceIdle = CIdle::NewL(CActive::EPriorityStandard);
}
/**
* Destructor
*/
CT_LbsHybridMultipleTest::~CT_LbsHybridMultipleTest()
{
if(iCheckNewSequenceIdle)
{
iCheckNewSequenceIdle->Cancel();
delete iCheckNewSequenceIdle;
}
delete iController;
}
/** Actual test step, which starts the test on the first sequence
*/
TVerdict CT_LbsHybridMultipleTest::doTestStepL()
{
INFO_PRINTF1(_L(""));
INFO_PRINTF1(_L("---------------------------------- Starting Test ----------------------------------"));
//Start off the master sequence; sequence 0
iActiveSequences = 1;
iSequences[0]->SignalCallbackIdleStart();
//This will cause the sequence to start its session; sending and receiving messages to LBS. The other
// sequences should start as this sequence progresses.
//Wait for the test to complete. When all the sequences have finished, the active scheduler will
// be stopped (from StopTest()) causing this test to complete.
CActiveScheduler::Start();
return TestStepResult();
}
/** Stops the active scheduler causing the test to finish
*
* @param aError If less than KErrNone, it will set the test step result to fail
*/
void CT_LbsHybridMultipleTest::StopTest(TInt aError)
{
//Check to see if we are ending the test in error
if(aError < 0)
{
//Fail the test step
SetTestStepResult(EFail);
}
CActiveScheduler::Stop();
}
/** Finds out which sequence relates to the session ID and checks that the received message was expected
*
* @param aSessionId Session ID that was past into the message
* @param aMessageType ID of the message that was received by the PM
*
* @return The ID of the sequence that this message relates to, or KErrNotFound
*/
TInt CT_LbsHybridMultipleTest::WasMessageExpectedSessionId(TInt aSessionId, TNetProtocolResponseType aMessageType)
{
//Loop through all the sequences
for(TInt i=0; i<iSequences.Count(); ++i)
{
//Get the session id and the current sequence action
TLbsNetSessionId sessionId = iSequences[i]->GetSessionId();
TInt currentAction = iSequences[i]->GetCurrentAction();
//Check the session ID of any sequence that is currently active with the session id past in
if((sessionId.SessionNum() == aSessionId) && (currentAction != KErrArgument))
{
//Found the sequence with the requested session id, now check if the message type was expected
if(currentAction == aMessageType)
{
//Message type was found, return sequence number
return i;
}
else
{
//Message not expected by this sequence
INFO_PRINTF3(_L("Error - Received unexpected message %d for session Id: %d"), aMessageType, aSessionId);
INFO_PRINTF3(_L(" -> On Sequence: %d, at position: %d"), i , iSequences[i]->GetCurrentPosition());
return KErrNotFound;
}
}
}
//Error, session ID not found in any sequence
INFO_PRINTF3(_L("Error - Received unexpected session Id (%d) for message: %d"), aSessionId, aMessageType);
return KErrNotFound;
}
/** Finds out whether any of the sequences (using aPmId) expected the following message
*
* @param aPmId ID of the PM that the message was received on (on sequences related to this id are checked)
* @param aMessageType ID of the message that was received by the PM
*
* @return The ID of the sequence that this message relates to, or KErrNotFound
*/
TInt CT_LbsHybridMultipleTest::WasMessageExpectedPmId(TInt aPmId, TNetProtocolResponseType aMessageType)
{
//Loop through all sequences
for(TInt i=0; i<iSequences.Count(); ++i)
{
//Check to see whether any sequences the are using PM ID, aPmId, are expecting this message
if((iSequences[i]->GetPmId() == aPmId) && (iSequences[i]->GetCurrentAction() == aMessageType))
{
//Return the sequenceId
return i;
}
}
//Error, message was not found in any of the sequences
INFO_PRINTF2(_L("Was not expecting message %d in any sequence"), aMessageType);
return KErrNotFound;
}
/* Called when one of the stub PM's receives a message from the NG
*
* @param aPmId The ID of the PM that received this message
* @param aMessageType The ID of the message type received from the PM
*/
void CT_LbsHybridMultipleTest::OnHandleNGMessage(TUint aPmId, TInt aMessageType)
{
//Get the correct proxy
CLbsTestNgMessageHandler* proxy = LookupProtocolModuleProxy(aPmId);
if (!proxy)
{
INFO_PRINTF2(_L("ERROR: No NG proxy setup for PM%d"), aPmId);
User::Leave(KErrNotFound);
}
TInt cleanupCnt;
TInt sequenceId = KErrNotFound;
//For each of the different message types, find out whether the message type was expected by the
// sequence (if a session Id is sent with the message) or by any sequence (if the session Id is not
// present). Then confirm the message parameters are expected and then move the correct sequence
// onto the next message.
switch(aMessageType)
{
// >> AdviceSystemStatus() [2009]
case ENetMsgGetCurrentCapabilitiesResponse:
{
sequenceId = WasMessageExpectedPmId(aPmId, ENetMsgGetCurrentCapabilitiesResponse);
INFO_PRINTF2(_L("-> AdviceSystemStatus() [2009] Sq: %d"), sequenceId);
if(sequenceId != KErrNotFound)
{
CLbsNetworkProtocolBase::TLbsSystemStatus status;
cleanupCnt = proxy->ProtocolProxy()->GetArgsLC(ENetMsgGetCurrentCapabilitiesResponse, &status);
TESTL(status == CLbsNetworkProtocolBase::ESystemStatusNone);
CleanupStack::PopAndDestroy(cleanupCnt);
}
break;
}
// >> RespondPrivacyRequest() [2000]
case ENetMsgRespondPrivacyRequest:
{
TLbsNetSessionId* getSessionId = NULL;
CLbsNetworkProtocolBase::TLbsPrivacyResponse getPrivacy;
cleanupCnt = proxy->ProtocolProxy()->GetArgsLC(ENetMsgRespondPrivacyRequest, &getSessionId, &getPrivacy);
sequenceId = WasMessageExpectedSessionId(getSessionId->SessionNum(), ENetMsgRespondPrivacyRequest);
INFO_PRINTF3(_L("-> RespondPrivacyRequest(%d) [2000] Sq: %d"), getPrivacy, sequenceId);
if(sequenceId != KErrNotFound)
{
iSequences[sequenceId]->CheckRespondPrivacyRequest(getPrivacy);
}
CleanupStack::PopAndDestroy(cleanupCnt);//getSessionId
break;
}
// >> RequestAssistanceData() [2004]
case ENetMsgRequestAssistanceData:
{
sequenceId = WasMessageExpectedPmId(aPmId, ENetMsgRequestAssistanceData);
//Request Assistance Data is a special case. Depending upon the timing of when the messages
// will be sent/received, it is not possible to predict in advance whether this message will
// always arrive in some of the later sequences. As such, a RequestAssistanceData message can
// arrive and even if it is not expected by any of the sequences, it will not fail the test.
if(sequenceId != KErrNotFound)
{
INFO_PRINTF2(_L("-> RequestAssistanceData() [2004] Sq: %d"), sequenceId);
TLbsAsistanceDataGroup dataGroup;
cleanupCnt = proxy->ProtocolProxy()->GetArgsLC(ENetMsgRequestAssistanceData, &dataGroup);
CleanupStack::PopAndDestroy(cleanupCnt);
}
else
{
//Message was not expected by any sequence. Manually set the Net Proxy off listening
// again, so the sequence can receive the message it expected.
INFO_PRINTF2(_L("-> RequestAssistanceData() [2004] Sq: unknown, PM: %d"), aPmId);
proxy->WaitForResponseL(80 * 1000 * 1000);
//Break out of the function now
return;
}
break;
}
// >> ResponsdLocationRequest() [2001]
case ENetMsgRespondLocationRequest:
{
TLbsNetSessionId* getSessionId = NULL;
getSessionId = NULL;
TInt getReason = KErrNone;
TPositionSatelliteInfo* getPositionInfo = NULL;
cleanupCnt = proxy->ProtocolProxy()->GetArgsLC(ENetMsgRespondLocationRequest, &getSessionId, &getReason, &getPositionInfo);
sequenceId = WasMessageExpectedSessionId(getSessionId->SessionNum(), ENetMsgRespondLocationRequest);
INFO_PRINTF3(_L("-> RespondLocationRequest(%d) [2001] Sq: %d"), getReason, sequenceId);
CleanupStack::PopAndDestroy(cleanupCnt);
break;
}
// >> RequestSelfLocation() [2005]
case ENetMsgRequestSelfLocation:
{
TLbsNetSessionId* sessionId = NULL;
TLbsNetPosRequestOptionsAssistance* opts = NULL;
cleanupCnt = proxy->ProtocolProxy()->GetArgsLC(ENetMsgRequestSelfLocation, &sessionId, &opts);
sequenceId = WasMessageExpectedPmId(aPmId, ENetMsgRequestSelfLocation);
INFO_PRINTF2(_L("-> RequestSelfLocation() [2005] Sq: %d"), sequenceId);
if(sequenceId != KErrNotFound)
{
iSequences[sequenceId]->CheckSelfLocationRequest(sessionId);
}
CleanupStack::PopAndDestroy(cleanupCnt);
break;
}
// >> CancelSelfLocation() [2006]
case ENetMsgCancelSelfLocation:
{
TLbsNetSessionId* sessionId = NULL;
TInt reason = 0;
cleanupCnt = proxy->ProtocolProxy()->GetArgsLC(ENetMsgCancelSelfLocation, &sessionId, &reason);
sequenceId = WasMessageExpectedSessionId(sessionId->SessionNum(), ENetMsgRequestSelfLocation);
INFO_PRINTF2(_L("-> CancelSelfLocation() [2006] Sq: %d"), sequenceId);
CleanupStack::PopAndDestroy(cleanupCnt);
break;
}
// >> RequestTransmitLocation() [2002]
case ENetMsgRequestTransmitLocation:
{
HBufC16* getThirdParty = NULL;
TLbsNetSessionId* getSessionId = NULL;
TInt getPriority(0);
TInt cleanupCnt;
cleanupCnt = proxy->ProtocolProxy()->GetArgsLC(ENetMsgRequestTransmitLocation, &getSessionId, &getThirdParty, &getPriority);
sequenceId = WasMessageExpectedPmId(aPmId, ENetMsgRequestTransmitLocation);
INFO_PRINTF2(_L("-> RequestTransmitLocation() [2002] Sq: %d"), sequenceId);
if(sequenceId != KErrNotFound)
{
iSequences[sequenceId]->CheckRequestTransmitLocation(getSessionId, getPriority, *getThirdParty);
}
CleanupStack::PopAndDestroy(cleanupCnt);
break;
}
// >> CancelTransmitLocation() [2003]
case ENetMsgCancelTransmitLocation:
{
TLbsNetSessionId* sessionId = NULL;
TInt reason = 0;
cleanupCnt = proxy->ProtocolProxy()->GetArgsLC(ENetMsgCancelTransmitLocation, &sessionId, &reason);
sequenceId = WasMessageExpectedSessionId(sessionId->SessionNum(), ENetMsgCancelTransmitLocation);
INFO_PRINTF2(_L("-> CancelTransmitLocation() [2003] Sq: %d"), sequenceId);
CleanupStack::PopAndDestroy(cleanupCnt);
break;
}
// >> RequestNetworkLocation() [2007]
case ENetMsgRequestNetworkLocation:
{
TLbsNetSessionId* sessionId = NULL;
TLbsNetPosRequestOptionsAssistance* opts = NULL;
cleanupCnt = proxy->ProtocolProxy()->GetArgsLC(ENetMsgRequestNetworkLocation, &sessionId, &opts);
sequenceId = WasMessageExpectedPmId(aPmId, ENetMsgRequestNetworkLocation);
INFO_PRINTF2(_L("-> RequestNetworkLocation() [2007] Sq: %d"), sequenceId);
if(sequenceId != KErrNotFound)
{
iSequences[sequenceId]->CheckNetworkLocationRequest(sessionId);
}
break;
}
// >> CancelNetworkLocation [2008]
case ENetMsgCancelNetworkLocation:
{
sequenceId = WasMessageExpectedPmId(aPmId, ENetMsgCancelNetworkLocation);
INFO_PRINTF2(_L("-> CancelNetworkLocation() [2008] Sq: %d"), sequenceId);
//NOTE: Currently no handling implemented for this message type
break;
}
// Timeout occurred waiting for a NG Message
case -1000:
{
INFO_PRINTF2(_L("Error - Timeout occurred waiting for NG message on PM: %d"), aPmId);
break;
}
//Error occurred, not a recognised message. Fail the test.
default:
{
INFO_PRINTF3(_L("Error - Received invalid NG message: %d on PM: %d"), aMessageType, aPmId);
return StopTest(KErrArgument);
}
}
//If the message was expected, continue the test
if(sequenceId != KErrNotFound)
{
iSequences[sequenceId]->SignalCallbackIdleStart();
}
else
{
// when an unexpected message arrives merley ignore and wait for next one!
proxy->WaitForResponseL(80 * 1000 * 1000);
}
}
/** Checks to see whether any of the other sequences should be started.
*/
void CT_LbsHybridMultipleTest::CheckForNewSequenceToStart()
{
TBool check = EFalse;
//Check for other sequences to start
for(TInt i=1; i<iSequences.Count(); ++i)
{
//Check to see whether this sequence has been started
TInt currentPosition = iSequences[i]->GetCurrentPosition();
if(iSequences[i]->GetCurrentPosition() >= 0)
{
//Sequence is started, move onto next sequence
continue;
}
//There are still sequences that need to be started, keep checking for new sequences
check = ETrue;
//Check to see whether this sequence needs to be started
if(iSequences[0]->GetCurrentPosition() >= iSequences[i]->GetStartPosition())
{
iActiveSequences++;
iSequences[i]->SignalCallbackIdleStart();
//Break, don't check any other sequences. This sequence has to be given a chance
// to start before trying to start any other sequences.
break;
}
}
// Set the check bool for future checks. If check is not set to ETrue above then no sequences
// are still waiting to be started, so there is no point in checking anymore.
iCheckForNewSequencesToStart = check;
}
TInt CT_LbsHybridMultipleTest::HandlerCompleteCallback(TAny* aAny)
{
reinterpret_cast<CT_LbsHybridMultipleTest*>(aAny)->HandlerCompleteNotify();
return KErrNone;
}
/** Handler Complete
*/
void CT_LbsHybridMultipleTest::HandlerCompleteNotify()
{
CheckForNewSequenceToStart();
}
/** Uses the TestExecute logger to allow the CTestSessionSequence class to log messages to
* the TestExecute log file.
*
* @param aMessage Contains the message that should be logged
*/
void CT_LbsHybridMultipleTest::LogTestStatement(const TDesC& aMessage)
{
INFO_PRINTF2(_L("%S"), &aMessage);
}
/** Signals the the sequence has finished. Check to see if the test should now end
*/
void CT_LbsHybridMultipleTest::SequenceFinished()
{
//This sequence is finished
iActiveSequences--;
//Check to see whether any other sequences are active
if(iActiveSequences > 0)
{
return;
}
else
{
//No active sequences, end the test
return StopTest(0);
}
}
/** Signal from the Test Sequence that the test should check for more sequences to start
*/
void CT_LbsHybridMultipleTest::SignalCheckForNewSequences()
{
if(iCheckForNewSequencesToStart)
{
iCheckNewSequenceIdle->Start(TCallBack(HandlerCompleteCallback, this));
}
}
/* >> ProcessNetworkLocationRequest()
*/
void CT_LbsHybridMultipleTest::ProcessNetworkLocationRequest(TUint aRequestId, const TLbsExternalRequestInfo& /*aRequestInfo*/, const TNotificationType& /*aNotificationType*/)
{
//Loop through the sequences identifying which sequence this privacy request belongs to
TInt i;
for(i=0; i<iSequences.Count(); ++i)
{
if(iSequences[i]->GetSessionId().SessionNum() == aRequestId)
{
INFO_PRINTF2(_L("--> ProcessNetworkLocationRequest() [3000] Sq: %d"), i);
if(iSequences[i]->GetCurrentAction() == EProcessNetworkLocationRequest)
{
iSequences[i]->SignalCallbackIdleStart();
}
break;
}
}
INFO_PRINTF2(_L("<-- RespondNetworkLocationRequest() Sq: %d"), i);
iController->RespondNetworkLocationRequest(aRequestId, CLbsPrivacyController::ERequestAccepted);
}
/** >> ProcessNetworkLocationUpdate()
*/
void CT_LbsHybridMultipleTest::ProcessNetworkPositionUpdate(TUint aRequestId, const TPositionInfo& /*aPosInfo*/)
{
for(TInt i=0; i<iSequences.Count(); ++i)
{
if(iSequences[i]->GetSessionId().SessionNum() == aRequestId)
{
INFO_PRINTF2(_L("--> ProcessNetworkPositionUpdate() [3001] Sq: %d"), i);
if(iSequences[i]->GetCurrentAction() == EProcessNetworkPositionUpdate)
{
iSequences[i]->SignalCallbackIdleStart();
}
break;
}
}
}
/** >> ProcessRequestComplete()
*/
void CT_LbsHybridMultipleTest::ProcessRequestComplete(TUint aRequestId, TInt aReason)
{
for(TInt i=0; i<iSequences.Count(); ++i)
{
if(iSequences[i]->GetSessionId().SessionNum() == aRequestId)
{
INFO_PRINTF3(_L("--> ProcessRequestComplete(%d) [3002] Sq: %d"), aReason, i);
if(iSequences[i]->GetCurrentAction() == EProcessRequestComplete)
{
iSequences[i]->SignalCallbackIdleStart();
}
break;
}
}
}