diff -r 9ddb1d67ebaf -r 9644881fedd0 datacommsserver/esockserver/test/providers/dummy/src/dummypr_subconnprov.cpp --- a/datacommsserver/esockserver/test/providers/dummy/src/dummypr_subconnprov.cpp Tue May 11 17:20:19 2010 +0300 +++ b/datacommsserver/esockserver/test/providers/dummy/src/dummypr_subconnprov.cpp Tue May 25 14:00:39 2010 +0300 @@ -93,8 +93,46 @@ return (iContext.iMessage.IsMessage() && TCprConfigModifier::Is(selectionInfo->CprConfig(), TCprConfigModifier::ESCPRHangOnStart)); } + +DEFINE_SMELEMENT(TCancelPreviousSelfRequest, NetStateMachine::MStateTransition, DummySCPRStates::TContext) +void TCancelPreviousSelfRequest::DoL() + { + iContext.iNodeActivity->PostRequestTo(iContext.Node().Id(), Messages::TEBase::TCancel().CRef()); + } + +DEFINE_SMELEMENT(TRebindSelf, NetStateMachine::MStateTransition, DummySCPRStates::TContext) +void TRebindSelf::DoL() + { + iContext.iNodeActivity->PostRequestTo(iContext.Node().Id(), TCFDataClient::TBindTo(Messages::TNodeId::NullId()).CRef()); + } + + + + +CrazyIdle::~CrazyIdle() + { + ASSERT(PostedToNodeId()==Messages::TNodeId::NullId()); + } + +MeshMachine::CNodeActivityBase* CrazyIdle::NewL(const MeshMachine::TNodeActivity& aActivitySig, MeshMachine::AMMNodeBase& aNode) + { + return new(ELeave)CrazyIdle(aActivitySig, aNode); + } + +DEFINE_SMELEMENT(CrazyIdle::TAwaitingCancelled, NetStateMachine::MState, DummySCPRStates::TContext) +TBool CrazyIdle::TAwaitingCancelled::Accept() + { + if (iContext.iMessage.IsMessage()) + { + ASSERT(iContext.iNodeActivity); + iContext.iNodeActivity->SetPostedTo(iContext.iNodeActivity->SoleOriginator().Peer().RecipientId()); + } + return EFalse; + } } + + namespace DummySCprParamsRequest { #ifdef SYMBIAN_ADAPTIVE_TCP_RECEIVE_WINDOW @@ -134,6 +172,41 @@ NODEACTIVITY_END() } +namespace CrazyIdleActivity +{ +//CrazyIdleActivity is used to test yet another angle of the meshmachine cancelling behaviour. +//What it does is: +//(1) responds to TIdle with an attempt to bind the sender, then, without waiting for the bind to complete +//(2) responds to TIdle normally (by deleting the sender) +//(3) cancells the bind request +//What it tests is: +//For two related nodes and upon the teardown of their relation there is an obligation to synchronise the activities +//running on the nodes and awaiting responses from each other. This obligation is put on the requestee, i.e.: a node that perfomes +//an activity on behalf of a leaving node should gracefully terminate that activity (by having the activity respond to the requestor. +//That obligation therefore doesn't rest on the requestor (someone, but not everyone, needs to do something). +//There's trivial race condition arising from this distribution of responsibility, i.e.: the requestor activity may decide to +//cancel when the relation is being terminated and TCancel may hit void. Activities must be resilient to this and not send +//TCancels to disappearing nodes. CrazyIdleActivity tests precislely this: it initaites an activity (TBindTo), then tears down the +//relation and cancels the previously initiated activity (TBindTo). CrazyIdleActivity must wrap up gracefully. +DECLARE_DEFINE_CUSTOM_NODEACTIVITY(ECFActivityDataClientIdle, crazyIdle, TCFControlProvider::TIdle, DummySCPRStates::CrazyIdle::NewL) + FIRST_NODEACTIVITY_ENTRY(CoreNetStates::TAwaitingDataClientIdle, MeshMachine::TNoTag) + //Issue TBindTo to self (this will then bind the data client reporting TIdle). Wait for BindTo activity to start before + //telling the dataclient to go away (TDestroy) as otherwise TBindTo won't make it in sending TBindTo to the dataclient. + THROUGH_NODEACTIVITY_ENTRY(KNoTag, DummySCPRStates::TRebindSelf, DummySCPRStates::TNoTagWaitForBindTo) + THROUGH_NODEACTIVITY_ENTRY(KNoTag, CoreNetStates::THandleDataClientIdle, MeshMachine::TNoTag) + //There's an additional test peformed by DummySCPRStates::CrazyIdle::TAwaitingCancelled. The state sets the postedto of CrazyIdle + //to point at the dataclient and CrazyIdle::~CrazyIdle asserts that that postedto is cleared. Currently PostedTo isn't cleared automatically - some people + //argued that it shouldn't and that activities should clear postedto whenever it's good for them. Unfortunatelly some activities are + //a bit lousy doing this and in result they can store a postedto pointing a node that has responded to the request a long time ago + //and above all a node that may have a long time ago left. A facility has been added to meshmachine to clear postedto when the node pointed + //at it actually leaves. This facility is tested collectivelly by DummySCPRStates::CrazyIdle::TAwaitingCancelled and CrazyIdle::~CrazyIdle + NODEACTIVITY_ENTRY(KNoTag, DummySCPRStates::TCancelPreviousSelfRequest, DummySCPRStates::CrazyIdle::TAwaitingCancelled, DummySCPRStates::TNoTagWaitNoDataClients) + LAST_NODEACTIVITY_ENTRY(KNoTag, MeshMachine::TDoNothing) +NODEACTIVITY_END() +} + + + // Activity Map For test-code ridden scpr namespace DummySCPRStates { @@ -141,7 +214,8 @@ ACTIVITY_MAP_ENTRY(DummySCprParamsRequest, dummySCprParamRequest) ACTIVITY_MAP_ENTRY(DummyBindToActivity, dummyBindTo) ACTIVITY_MAP_ENTRY(DummyBreakStartActivity, dummyBreakSCPrStart) - ACTIVITY_MAP_ENTRY(DummyStartActivity, dummySCPrStart) + ACTIVITY_MAP_ENTRY(DummyStartActivity, dummySCPrStart) + ACTIVITY_MAP_ENTRY(CrazyIdleActivity, crazyIdle) ACTIVITY_MAP_END_BASE(SCprActivities, coreSCprActivities) } @@ -228,3 +302,5 @@ + +