[asterisk-scf-commits] asterisk-scf/integration/routing.git branch "route_replica" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Tue May 3 01:24:17 CDT 2011


branch "route_replica" has been updated
       via  5371f62b5bd84e2371d8ecfbe51e429a09f5a74d (commit)
      from  a6984b9b7ad5b5f0ba7db843876bc90949589dfd (commit)

Summary of changes:
 src/BasicRoutingServiceApp.cpp                     |    1 -
 ...nectBridgedSessionsWithDestinationOperation.cpp |  143 +++++++++-------
 ...onnectBridgedSessionsWithDestinationOperation.h |    6 +
 src/RouteSessionOperation.cpp                      |  151 ++++++++++-------
 src/RouteSessionOperation.h                        |    6 +
 src/RoutingStateReplicatorListener.cpp             |   46 +++++
 src/SessionRouterOperation.h                       |    8 +-
 test/MockEndpointLocator.cpp                       |    6 +
 test/MockEndpointLocator.h                         |    4 +
 test/SharedTestData.h                              |    2 +
 test/TestRouting.cpp                               |  175 ++++++++++++++++++++
 11 files changed, 425 insertions(+), 123 deletions(-)


- Log -----------------------------------------------------------------
commit 5371f62b5bd84e2371d8ecfbe51e429a09f5a74d
Author: Ken Hunt <ken.hunt at digium.com>
Date:   Tue May 3 01:23:32 2011 -0500

    Additional testing and bug fixes to verify the replicated operations function
    as expected.

diff --git a/src/BasicRoutingServiceApp.cpp b/src/BasicRoutingServiceApp.cpp
index 4e31eaa..26e0b8b 100644
--- a/src/BasicRoutingServiceApp.cpp
+++ b/src/BasicRoutingServiceApp.cpp
@@ -80,7 +80,6 @@ public:
           mWorkQueue( new AsteriskSCF::Threading::SimpleWorkQueue("SessionRouterWorkQueue")),
           mListeningToReplicator(false)
     {
-        lg.setLevel(Error);
     }
 
     ~BasicRoutingServiceApp()
diff --git a/src/ConnectBridgedSessionsWithDestinationOperation.cpp b/src/ConnectBridgedSessionsWithDestinationOperation.cpp
index 4c174f7..e985f52 100644
--- a/src/ConnectBridgedSessionsWithDestinationOperation.cpp
+++ b/src/ConnectBridgedSessionsWithDestinationOperation.cpp
@@ -68,18 +68,39 @@ public:
             return;
         }
 
-        if (state == ConnectBridgedSessionsWithDestinationOp::STATE_LOOKUP)
+        switch(state)
         {
-            // Push this information to the state replicator.
-            ConnectBridgedSessionsWithDestinationOpStartPtr 
-                 opStart(new ConnectBridgedSessionsWithDestinationOpStart());
-            opStart->operationId = mOperation->getOperationId();
-            opStart->key = mOperation->getOperationId() + 
-                 AsteriskSCF::BasicRoutingService::V1::ConnectBridgedSessionsWithDestStartKeyMod;
-            opStart->sessionToReplace = mOperation->getSessionToReplace();
-            opStart->destination = mOperation->getDestination();
-
-            pushState(opStart);
+        case ConnectBridgedSessionsWithDestinationOp::STATE_LOOKUP:
+            {
+                // Push this information to the state replicator.
+                ConnectBridgedSessionsWithDestinationOpStartPtr 
+                     opStart(new ConnectBridgedSessionsWithDestinationOpStart());
+                opStart->operationId = mOperation->getOperationId();
+                opStart->key = mOperation->getOperationId() + 
+                     AsteriskSCF::BasicRoutingService::V1::ConnectBridgedSessionsWithDestStartKeyMod;
+                opStart->sessionToReplace = mOperation->getSessionToReplace();
+                opStart->destination = mOperation->getDestination();
+
+                pushState(opStart);
+            }
+        break;
+
+        case ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING:
+            {
+            // We've obtained a result from our AMI lookup request.
+            ConnectBridgedSessionsWithDestinationOpWaitLookupStatePtr 
+                 waitLookup(new ConnectBridgedSessionsWithDestinationOpWaitLookupState());
+            waitLookup->operationId = mOperation->getOperationId();
+            waitLookup->key = mOperation->getOperationId() + 
+                 AsteriskSCF::BasicRoutingService::V1::RouteSessionOpWaitLookupKeyMod;
+            waitLookup->endpoints = mOperation->getLookupResult();
+
+            pushState(waitLookup);
+            }
+            break;
+
+        default:
+            break;
         }
     }
 
@@ -99,47 +120,6 @@ public:
      */
     void stateExecutionComplete(ConnectBridgedSessionsWithDestinationOp::OperationState state)
     {
-        if (!mReplicationContext->isReplicating())
-        {
-            return;
-        }
-
-        switch(state)
-        {
-        case ConnectBridgedSessionsWithDestinationOp::STATE_WAIT_LOOKUP_RESULTS:
-            {
-            // We just completed the entire operation. 
-            // Push this information to the state replicator.
-            ConnectBridgedSessionsWithDestinationOpWaitLookupStatePtr 
-                 waitLookup(new ConnectBridgedSessionsWithDestinationOpWaitLookupState());
-            waitLookup->operationId = mOperation->getOperationId();
-            waitLookup->key = mOperation->getOperationId() + 
-                 AsteriskSCF::BasicRoutingService::V1::RouteSessionOpWaitLookupKeyMod;
-            waitLookup->endpoints = mOperation->getLookupResult();
-
-            pushState(waitLookup);
-            }
-            break;
-
-        case ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING:
-            {
-            // We just completed creating a bridge. 
-            // Push this information to the state replicator.
-            ConnectBridgedSessionsWithDestinationOpBridgingStatePtr 
-                 bridgeOp(new ConnectBridgedSessionsWithDestinationOpBridgingState());
-            bridgeOp->operationId = mOperation->getOperationId();
-            bridgeOp->key = mOperation->getOperationId() + 
-                    AsteriskSCF::BasicRoutingService::V1::RouteSessionOpBridgingKeyMod;
-            bridgeOp->bridge = mOperation->getBridge();
-
-            pushState(bridgeOp);
-            }
-            break;
-
-        default:
-            break;
-
-        } // end switch
     }
 
     /**
@@ -169,9 +149,35 @@ public:
      *    @param oldState The state transitioning from.
      *    @param newState The state transitioning to.
      */
-    void stateTransition(ConnectBridgedSessionsWithDestinationOp::OperationState, 
+    void stateTransition(ConnectBridgedSessionsWithDestinationOp::OperationState oldState, 
                          ConnectBridgedSessionsWithDestinationOp::OperationState)
     {
+        if (!mReplicationContext->isReplicating())
+        {
+            return;
+        }
+
+        switch(oldState)
+        {
+        case ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING:
+            {
+            // We just completed creating a bridge. 
+            // Push this information to the state replicator.
+            ConnectBridgedSessionsWithDestinationOpBridgingStatePtr 
+                 bridgeOp(new ConnectBridgedSessionsWithDestinationOpBridgingState());
+            bridgeOp->operationId = mOperation->getOperationId();
+            bridgeOp->key = mOperation->getOperationId() + 
+                    AsteriskSCF::BasicRoutingService::V1::RouteSessionOpBridgingKeyMod;
+            bridgeOp->bridge = mOperation->getBridge();
+
+            pushState(bridgeOp);
+            }
+            break;
+
+        default:
+            break;
+
+        } // end switch
     }
 
 private:
@@ -333,7 +339,7 @@ bool ConnectBridgedSessionsWithDestinationOperation::fastForwardReplica()
         return false;
     }
     // Set to initial state.
-    mStateMachine.setNextState(ConnectBridgedSessionsWithDestinationOp::STATE_LOOKUP);
+    mStateMachine.resetStartState(ConnectBridgedSessionsWithDestinationOp::STATE_LOOKUP);
 
     // See if we got the results from the lookup.
     i = find(mReplicatedStates.begin(), mReplicatedStates.end(), ConnectBridgedSessionsWithDestinationOp::STATE_WAIT_LOOKUP_RESULTS);
@@ -341,7 +347,9 @@ bool ConnectBridgedSessionsWithDestinationOperation::fastForwardReplica()
     {
         return true;
     }
-    mStateMachine.setNextState(ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING);
+
+    addListenerManager();
+    mStateMachine.resetStartState(ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING);
 
     // See if we got past bridge creation.
     i = find(mReplicatedStates.begin(), mReplicatedStates.end(), ConnectBridgedSessionsWithDestinationOp::STATE_BRIDGING);
@@ -351,10 +359,15 @@ bool ConnectBridgedSessionsWithDestinationOperation::fastForwardReplica()
     }
 
     // Apparently nothing left to do but reply to the AMD callback. 
-    mStateMachine.setNextState(ConnectBridgedSessionsWithDestinationOp::STATE_SEND_RESPONSE);
+    mStateMachine.resetStartState(ConnectBridgedSessionsWithDestinationOp::STATE_SEND_RESPONSE);
     return true;
 }
 
+void ConnectBridgedSessionsWithDestinationOperation::addListenerManager()
+{
+    mListenerManager.reset(new SessionListenerManager(mSessionContext->adapter, this->mSessionToReplace));
+}
+
 /**
  * This is a state handler for one of this operation's states. 
  */
@@ -382,11 +395,7 @@ void ConnectBridgedSessionsWithDestinationOperation::lookupState()
         return;
     }
 
-    // Create a listener for the sessions not being replaced to handle early termination.
-    // The wrapper we're using will remove the listener and free it when
-    // this method is left.
-    lg(Debug) << BOOST_CURRENT_FUNCTION << ": Attaching listener";
-    mListenerManager = SessionListenerManagerPtr(new SessionListenerManager(mSessionContext->adapter, mSessionToReplace));
+    addListenerManager();
 
     // Route the destination
     lg(Debug) << BOOST_CURRENT_FUNCTION << ": Routing destination " << mDestination;
@@ -482,6 +491,18 @@ void ConnectBridgedSessionsWithDestinationOperation::establishBridgeState()
         return;
     }
 
+    // Test instrumentation
+    if (mSessionContext->replicationContext->getTestContext().get() != 0)
+    {
+        if (mSessionContext->replicationContext->getTestContext()->getTestMode() == "ConnectBridgedSessWithDestFailover")
+        {
+            // We're going to just shutdown this operation right here, with no replies to the caller. 
+            // This is so that an external test can verify the replica can take it the rest of the way.
+            finish();
+            return;
+        }
+    }
+
     // Set the state handler to exectute once we've looked up our endpoints. 
     mStateMachine.setNextState(ConnectBridgedSessionsWithDestinationOp::STATE_SEND_RESPONSE);
 
diff --git a/src/ConnectBridgedSessionsWithDestinationOperation.h b/src/ConnectBridgedSessionsWithDestinationOperation.h
index 8e00ece..ce1fa63 100644
--- a/src/ConnectBridgedSessionsWithDestinationOperation.h
+++ b/src/ConnectBridgedSessionsWithDestinationOperation.h
@@ -149,6 +149,12 @@ private:
      */
     void sendResponseState();
 
+    /**
+     * Add listener to watch fo early termination of the operation
+     * by the client. 
+     */
+    void addListenerManager();
+
 private:
     // Operation input params. 
     AsteriskSCF::SessionCommunications::V1::SessionPrx mSessionToReplace;
diff --git a/src/RouteSessionOperation.cpp b/src/RouteSessionOperation.cpp
index 3710edc..d7ce95d 100644
--- a/src/RouteSessionOperation.cpp
+++ b/src/RouteSessionOperation.cpp
@@ -20,6 +20,7 @@
 
 #include "BasicRoutingStateReplicationIf.h"
 #include "RouteSessionOperation.h"
+#include "TestContext.h"
 
 using namespace AsteriskSCF;
 using namespace AsteriskSCF::Core::Routing::V1;
@@ -69,18 +70,38 @@ public:
             return;
         }
 
-        if (state == RouteSessionOp::STATE_LOOKUP)
+        switch(state)
         {
-            // This is the initial state. All the state of interest is what's been passed in.
-            // Push this information to the state replicator.
-            RouteSessionOpStartPtr routeSessionOpStart(new RouteSessionOpStart());
-            routeSessionOpStart->operationId =  mOperation->getOperationId();
-            routeSessionOpStart->key = mOperation->getOperationId() + 
-                  AsteriskSCF::BasicRoutingService::V1::RouteSessionOpStartKeyMod;
-            routeSessionOpStart->source = mOperation->getSource();
-            routeSessionOpStart->destination = mOperation->getDestination();
-
-            pushState(routeSessionOpStart);
+        case RouteSessionOp::STATE_LOOKUP:
+            {
+                // This is the initial state. All the state of interest is what's been passed in.
+                // Push this information to the state replicator.
+                RouteSessionOpStartPtr routeSessionOpStart(new RouteSessionOpStart());
+                routeSessionOpStart->operationId =  mOperation->getOperationId();
+                routeSessionOpStart->key = mOperation->getOperationId() + 
+                      AsteriskSCF::BasicRoutingService::V1::RouteSessionOpStartKeyMod;
+                routeSessionOpStart->source = mOperation->getSource();
+                routeSessionOpStart->destination = mOperation->getDestination();
+
+                pushState(routeSessionOpStart);
+            }
+            break;
+
+        case RouteSessionOp::STATE_BRIDGING:
+            {
+            // We've obtained a result from our AMI lookup request.
+            RouteSessionOpWaitLookupStatePtr routeSessionOpWaitLookup(new RouteSessionOpWaitLookupState());
+            routeSessionOpWaitLookup->operationId =  mOperation->getOperationId();
+            routeSessionOpWaitLookup->key = mOperation->getOperationId() + 
+                 AsteriskSCF::BasicRoutingService::V1::RouteSessionOpWaitLookupKeyMod;
+            routeSessionOpWaitLookup->endpoints = mOperation->getLookupResult();
+
+            pushState(routeSessionOpWaitLookup);
+            }
+            break;
+
+        default:
+             break;
         }
     }
 
@@ -100,47 +121,7 @@ public:
      */
     void stateExecutionComplete(RouteSessionOp::OperationState state)
     {
-        if (!mReplicationContext->isReplicating())
-        {
-            return;
-        }
 
-        switch(state)
-        {
-        case RouteSessionOp::STATE_WAIT_LOOKUP_RESULTS:
-            {
-            // We've obtained a result from our AMI lookup request.
-            RouteSessionOpWaitLookupStatePtr routeSessionOpWaitLookup(new RouteSessionOpWaitLookupState());
-            routeSessionOpWaitLookup->operationId =  mOperation->getOperationId();
-            routeSessionOpWaitLookup->key = mOperation->getOperationId() + 
-                 AsteriskSCF::BasicRoutingService::V1::RouteSessionOpWaitLookupKeyMod;
-            routeSessionOpWaitLookup->endpoints = mOperation->getLookupResult();
-
-            pushState(routeSessionOpWaitLookup);
-            }
-            break;
-
-        case RouteSessionOp::STATE_BRIDGING:
-            {
-            // We just completed the bridge creation.
-            // Push this information to the state replicator.
-            RouteSessionOpBridgingStatePtr routeSessionOpBridging(new RouteSessionOpBridgingState());
-            routeSessionOpBridging->operationId =  mOperation->getOperationId();
-            routeSessionOpBridging->key = mOperation->getOperationId() + 
-                 AsteriskSCF::BasicRoutingService::V1::RouteSessionOpBridgingKeyMod;
-            routeSessionOpBridging->bridge = mOperation->getBridge();
-
-            pushState(routeSessionOpBridging);
-            }
-            break;
-
-        case RouteSessionOp::STATE_SEND_RESPONSE:
-            // The AMD caller has been notified. We'll remove the replica in shutdown() handler. 
-            break;
-
-        default:
-            break;
-        }
     }
 
     /**
@@ -168,9 +149,37 @@ public:
     /**
      * This callback is called when a state transition is occuring. 
      */
-    void stateTransition(RouteSessionOp::OperationState, // oldState 
+    void stateTransition(RouteSessionOp::OperationState oldState, // oldState 
                          RouteSessionOp::OperationState) // newState
     {
+        if (!mReplicationContext->isReplicating())
+        {
+            return;
+        }
+
+        switch(oldState)
+        {
+        case RouteSessionOp::STATE_BRIDGING:
+            {
+            // We just completed the bridge creation.
+            // Push this information to the state replicator.
+            RouteSessionOpBridgingStatePtr routeSessionOpBridging(new RouteSessionOpBridgingState());
+            routeSessionOpBridging->operationId =  mOperation->getOperationId();
+            routeSessionOpBridging->key = mOperation->getOperationId() + 
+                 AsteriskSCF::BasicRoutingService::V1::RouteSessionOpBridgingKeyMod;
+            routeSessionOpBridging->bridge = mOperation->getBridge();
+
+            pushState(routeSessionOpBridging);
+            }
+            break;
+
+        case RouteSessionOp::STATE_SEND_RESPONSE:
+            // The AMD caller has been notified. We'll remove the replica in shutdown() handler. 
+            break;
+
+        default:
+            break;
+        }
     }
 
 private:
@@ -330,7 +339,7 @@ bool RouteSessionOperation::fastForwardReplica()
         return false;
     }
     // Set to initial state.
-    mStateMachine.setNextState(RouteSessionOp::STATE_LOOKUP);
+    mStateMachine.resetStartState(RouteSessionOp::STATE_LOOKUP);
 
     // See if we got the results from the lookup.
     i = find(mReplicatedStates.begin(), mReplicatedStates.end(), RouteSessionOp::STATE_WAIT_LOOKUP_RESULTS);
@@ -338,7 +347,12 @@ bool RouteSessionOperation::fastForwardReplica()
     {
         return true;
     }
-    mStateMachine.setNextState(RouteSessionOp::STATE_BRIDGING);
+  
+    addListenerManager();
+
+    lg(Debug) << "Fast-forwarded replica of RouteSessionOperation to STATE_BRIDGING for " << mOperationId;
+
+    mStateMachine.resetStartState(RouteSessionOp::STATE_BRIDGING);
 
     // See if we got past bridge creation.
     i = find(mReplicatedStates.begin(), mReplicatedStates.end(), RouteSessionOp::STATE_BRIDGING);
@@ -348,7 +362,8 @@ bool RouteSessionOperation::fastForwardReplica()
     }
 
     // Apparently nothing left to do but reply to the AMD callback. 
-    mStateMachine.setNextState(RouteSessionOp::STATE_SEND_RESPONSE);
+    lg(Debug) << "Fast-forwarded replica of RouteSessionOperation to STATE_SEND_RESPONSE for " << mOperationId;
+    mStateMachine.resetStartState(RouteSessionOp::STATE_SEND_RESPONSE);
     return true;
 }
 
@@ -358,6 +373,14 @@ RouteSessionOperation::~RouteSessionOperation()
 }
 
 /**
+ * Create a listener for the source to handle early termination.
+ */
+void RouteSessionOperation::addListenerManager()
+{
+    mListenerManager.reset(new SessionListenerManager(mSessionContext->adapter, mSource));
+}
+
+/**
  * This is a state handler for one of this operation's states. 
  * This method is called via mCurrentStateHandler when doWork() is executed from the 
  * WorkQueue. 
@@ -375,11 +398,7 @@ void RouteSessionOperation::lookupState()
         return;
     }
 
-    // Create a listener for the source to handle early termination.
-    // The wrapper we're using will remove the listener and free it when
-    // this method is left.
-    SessionListenerManagerPtr listener(new SessionListenerManager(mSessionContext->adapter, mSource));
-    mListenerManager = listener;
+    addListenerManager();
 
     // Set the state handler to exectute once we've looked up our endpoints. 
     mStateMachine.setNextState(RouteSessionOp::STATE_WAIT_LOOKUP_RESULTS);
@@ -422,6 +441,18 @@ void RouteSessionOperation::establishBridgeState()
         return;
     }
 
+    // Test instrumentation
+    if (mSessionContext->replicationContext->getTestContext().get() != 0)
+    {
+        if (mSessionContext->replicationContext->getTestContext()->getTestMode() == "RouteSessionFailover")
+        {
+            // We're going to just shutdown this operation right here, with no replies to the caller. 
+            // This is so that an external test can verify the replica can take it the rest of the way.
+            finish();
+            return;
+        }
+    }
+
     assert(mLookupResult.size() > 0); // This exception should have been handled in EndpointRegistry. 
 
     if (mLookupResult.size() < 1)
diff --git a/src/RouteSessionOperation.h b/src/RouteSessionOperation.h
index 2f8059c..39d96e9 100644
--- a/src/RouteSessionOperation.h
+++ b/src/RouteSessionOperation.h
@@ -162,6 +162,12 @@ private:
      */
     void sendResponseState();
 
+    /**
+     * Add listener to watch fo early termination of the operation
+     * by the client. 
+     */
+    void addListenerManager();
+
 private:
     // Operation input params. 
     AsteriskSCF::SessionCommunications::V1::SessionPrx mSource;
diff --git a/src/RoutingStateReplicatorListener.cpp b/src/RoutingStateReplicatorListener.cpp
index 3f0691e..f811416 100644
--- a/src/RoutingStateReplicatorListener.cpp
+++ b/src/RoutingStateReplicatorListener.cpp
@@ -131,6 +131,52 @@ public:
             RoutingStateReplicatorListenerPriv *mImpl;
             const Ice::Current& mCurrent;
 
+            // Used an intermediate class in the slice types, and the visitor didn't pick up the leaf classes to visit. 
+            void visitOperationStateItem(const ::AsteriskSCF::BasicRoutingService::V1::OperationStateItemPtr& operation)
+            {
+                RouteSessionOpStartPtr routeSessinOpStart = RouteSessionOpStartPtr::dynamicCast(operation);
+                if (routeSessinOpStart != 0)
+                {
+                    visitRouteSessionOpStart(routeSessinOpStart);
+                    return;
+                }
+
+                RouteSessionOpWaitLookupStatePtr routeSessionWait = RouteSessionOpWaitLookupStatePtr::dynamicCast(operation);
+                if (routeSessionWait != 0)
+                {
+                    visitRouteSessionOpWaitLookupState(routeSessionWait);
+                    return;
+                }
+
+                RouteSessionOpBridgingStatePtr routeBridging = RouteSessionOpBridgingStatePtr::dynamicCast(operation);
+                if (routeBridging != 0)
+                {
+                    visitRouteSessionOpBridgingState(routeBridging);
+                    return;
+                }
+                  
+                ConnectBridgedSessionsWithDestinationOpStartPtr connectWithDestStart = ConnectBridgedSessionsWithDestinationOpStartPtr::dynamicCast(operation);
+                if (connectWithDestStart != 0)
+                {
+                    visitConnectBridgedSessionsWithDestinationOpStart(connectWithDestStart);
+                    return;
+                }
+
+                ConnectBridgedSessionsWithDestinationOpWaitLookupStatePtr connectWithDestLookup = ConnectBridgedSessionsWithDestinationOpWaitLookupStatePtr::dynamicCast(operation);
+                if (connectWithDestLookup != 0)
+                {
+                    visitConnectBridgedSessionsWithDestinationOpWaitLookupState(connectWithDestLookup);
+                    return;
+                }
+
+                ConnectBridgedSessionsWithDestinationOpBridgingStatePtr connectWithDestBridge = ConnectBridgedSessionsWithDestinationOpBridgingStatePtr::dynamicCast(operation);
+                if (connectWithDestBridge != 0)
+                {
+                    visitConnectBridgedSessionsWithDestinationOpBridgingState(connectWithDestBridge);
+                    return;
+                }
+            }
+
             void visitRouteSessionOpStart(const ::AsteriskSCF::BasicRoutingService::V1::RouteSessionOpStartPtr& opState)
             {
                 mImpl->mOperationReplicaCache->getRouteSessionCache()->cacheOperationState(opState);
diff --git a/src/SessionRouterOperation.h b/src/SessionRouterOperation.h
index 63b81cc..a02c9f9 100644
--- a/src/SessionRouterOperation.h
+++ b/src/SessionRouterOperation.h
@@ -242,9 +242,15 @@ public:
      */
     void setLookupResult(const AsteriskSCF::Core::Endpoint::V1::EndpointSeq& endpoints)
     {
+        if (mFinished)
+        {
+            // This operation terminated since the callback was created.
+            return;
+        }
+
         mLookupResult = endpoints;
 
-        // Reschedule this operation to complete.
+        // Reschedule this operation to continue.
         try
         {
             // Let the operation continue on its way. 
diff --git a/test/MockEndpointLocator.cpp b/test/MockEndpointLocator.cpp
index aacd0c7..32036c2 100644
--- a/test/MockEndpointLocator.cpp
+++ b/test/MockEndpointLocator.cpp
@@ -63,6 +63,8 @@ void MockEndpointLocator::lookup_async(const ::AsteriskSCF::Core::Routing::V1::A
         cb->ice_exception(DestinationNotFoundException(destination));
     }
     cb->ice_response(endpoints);
+
+    mLookupCalled = true;
 }
 
 void MockEndpointLocator::perTestCleanup()
@@ -71,6 +73,8 @@ void MockEndpointLocator::perTestCleanup()
     {
         (*i)->perTestCleanup();
     }
+
+    mLookupCalled = false;
 }
 
 void MockEndpointLocator::clear()
@@ -82,6 +86,8 @@ void MockEndpointLocator::clear()
 
     mEndpointPrxList.clear();
     mEndpoints.clear();
+
+    mLookupCalled = false;
 }
 
 MockSessionEndpointPtr MockEndpointLocator::addEndpoint(const string& id)
diff --git a/test/MockEndpointLocator.h b/test/MockEndpointLocator.h
index 0230cde..9eb20f3 100644
--- a/test/MockEndpointLocator.h
+++ b/test/MockEndpointLocator.h
@@ -30,6 +30,8 @@ namespace RoutingTest
 class MockEndpointLocator : public AsteriskSCF::Core::Routing::V1::EndpointLocator
 {
 public:
+    MockEndpointLocator() : mLookupCalled(false) {}
+
     // Overrides
     virtual void lookup_async(const ::AsteriskSCF::Core::Routing::V1::AMD_EndpointLocator_lookupPtr& cb, const ::std::string& destination, const ::Ice::Current& = ::Ice::Current());
 
@@ -43,6 +45,8 @@ public:
      */
     MockSessionEndpointPtr localLookup(const std::string& id);
 
+    bool mLookupCalled;
+
 private:
     AsteriskSCF::Core::Endpoint::V1::EndpointSeq mEndpointPrxList;
     std::vector<MockSessionEndpointPtr> mEndpoints;
diff --git a/test/SharedTestData.h b/test/SharedTestData.h
index a82c213..8d34545 100644
--- a/test/SharedTestData.h
+++ b/test/SharedTestData.h
@@ -49,6 +49,8 @@ struct SharedTestData
     AsteriskSCF::Core::Routing::V1::LocatorRegistryPrx locatorRegistry;
     AsteriskSCF::SessionCommunications::V1::SessionRouterPrx sessionRouter;
     AsteriskSCF::System::Component::V1::ReplicaPrx serviceReplicaMgmt;
+    AsteriskSCF::System::Component::V1::ComponentServicePrx componentService;
+    AsteriskSCF::System::Component::V1::ComponentTestPrx componentTest;
 
     // Proxies to the backup instance's routing service interfaces.
     AsteriskSCF::Core::Routing::V1::LocatorRegistryPrx backupLocatorRegistry;
diff --git a/test/TestRouting.cpp b/test/TestRouting.cpp
index ef4b05c..48abb23 100644
--- a/test/TestRouting.cpp
+++ b/test/TestRouting.cpp
@@ -91,6 +91,21 @@ struct GlobalIceFixture
             SharedTestData::instance.communicatorOut = Ice::initialize(initData);
             SharedTestData::instance.adapterOut = SharedTestData::instance.communicatorOut->createObjectAdapterWithEndpoints("TestRoutingAdapterOut", "default -p 10071");
 
+            // Get ref to Routing Service's ComponentService interface. 
+            Ice::ObjectPrx componentObj = SharedTestData::instance.communicatorOut->propertyToProxy("RoutingComponent.Proxy");
+            SharedTestData::instance.componentService = ComponentServicePrx::uncheckedCast(componentObj);
+
+            if (!SharedTestData::instance.componentService)
+            {
+                throw "Invalid ComponentService";
+            }
+
+            SharedTestData::instance.componentTest = ComponentTestPrx::checkedCast(SharedTestData::instance.componentService, AsteriskSCF::System::Component::V1::ComponentTestFacet);
+            if (SharedTestData::instance.componentTest == 0)
+            {
+                BOOST_TEST_MESSAGE("No Component Test facet available. Some tests may be skipped.");
+            }
+
             // Get ref to Routing Service EndpointLocator so we can test it. Getting direct for now, but
             // need to test acquiring reference via ServiceLocator as well.
             Ice::ObjectPrx locatorObj = SharedTestData::instance.communicatorOut->propertyToProxy("LocatorRegistry.Proxy");
@@ -697,3 +712,163 @@ BOOST_FIXTURE_TEST_CASE(SwitchActiveAndStandby, PerTestFixture)
 
 }
 
+BOOST_FIXTURE_TEST_CASE(FailoverRouteSession, PerTestFixture)
+{
+    if (SharedTestData::instance.componentTest == 0)
+    {
+        BOOST_TEST_MESSAGE("Component test interface not configured. Skipping test FailoverRouteSession.");
+        return;
+    }
+
+    try
+    {
+        // Verify that both the active and standby services report the correct state.
+        BOOST_CHECK(SharedTestData::instance.serviceReplicaMgmt->isActive() == true);
+        BOOST_CHECK(SharedTestData::instance.backupServiceReplicaMgmt->isActive() == false);
+
+        SharedTestData::instance.componentTest->setTestMode("RouteSessionFailover");
+
+        // Get our local 101 endpoint
+        MockSessionEndpointPtr session101Endpoint = SharedTestData::instance.endpointLocator->localLookup("101");
+
+        BOOST_TEST_MESSAGE("Creating a session on our test endpoint...");
+        SessionPrx session = session101Endpoint->createSession("102", 0, Ice::Current());
+        BOOST_CHECK(session != 0);
+
+        SharedTestData::instance.mBridgeConnected = false;
+
+        BOOST_TEST_MESSAGE("Routing the session...");
+        string operationId = IceUtil::generateUUID();
+
+        // Note we're routing using AMI with no callback. The callback would never come due to the
+        // way the test mode shuts down the operation. Simulates failure.
+        SharedTestData::instance.sessionRouter->begin_routeSession(operationId, session, "102");
+
+        for (int counter=0; SharedTestData::instance.endpointLocator->mLookupCalled == false; counter++)
+        {
+           // Give the main routing service time to do the lookup. 
+            IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(500));
+
+            if (counter > 5)
+            {
+                // Must be other problems!
+                break;
+            }
+        }
+
+        // The lookup should have completed prior to the simulated failure.
+        BOOST_CHECK(SharedTestData::instance.endpointLocator->mLookupCalled);
+
+        // In test mode, the active routing service will abort the operation prior to
+        // createing the bridge.
+        BOOST_CHECK(SharedTestData::instance.mBridgeConnected == false);
+
+        // Reset the lookup flag. 
+        SharedTestData::instance.endpointLocator->mLookupCalled = false;
+
+        // Switch standby component to active. 
+        SharedTestData::instance.serviceReplicaMgmt->activate();
+        BOOST_CHECK(SharedTestData::instance.serviceReplicaMgmt->isActive() == true);
+
+        // Let the backup session router try to route using same operationId.
+        SharedTestData::instance.backupSessionRouter->routeSession(operationId, session, "102");
+
+        // The lookup should not be done again. 
+        BOOST_CHECK(!SharedTestData::instance.endpointLocator->mLookupCalled);
+
+        BOOST_CHECK(SharedTestData::instance.mBridgeConnected == true);
+
+        // Set the backup back into standby mode.
+        SharedTestData::instance.backupServiceReplicaMgmt->standby();
+        BOOST_CHECK(SharedTestData::instance.backupServiceReplicaMgmt->isActive() == false);
+    }
+    catch (...)
+    {
+        BOOST_FAIL("Exception switching component between active and standby.");
+    }
+
+}
+
+BOOST_FIXTURE_TEST_CASE(FailoverConnectBridgedSessWithDest, PerTestFixture)
+{
+    if (SharedTestData::instance.componentTest == 0)
+    {
+        BOOST_TEST_MESSAGE("Component test interface not configured. Skipping test FailoverConnectBridgedSessWithDest.");
+        return;
+    }
+
+    try
+    {
+        // Verify that both the active and standby services report the correct state.
+        BOOST_CHECK(SharedTestData::instance.serviceReplicaMgmt->isActive() == true);
+        BOOST_CHECK(SharedTestData::instance.backupServiceReplicaMgmt->isActive() == false);
+
+        SharedTestData::instance.componentTest->setTestMode("ConnectBridgedSessWithDestFailover");
+
+        // Get our local 101 endpoint
+        MockSessionEndpointPtr session101Endpoint = SharedTestData::instance.endpointLocator->localLookup("101");
+
+        BOOST_TEST_MESSAGE("Creating a session on our test endpoint...");
+        SessionPrx session = session101Endpoint->createSession("102", 0, Ice::Current());
+        BOOST_CHECK(session != 0);
+
+        SharedTestData::instance.mBridgeConnected = false;
+        SharedTestData::instance.mSessionReplaced = false;
+
+        BOOST_TEST_MESSAGE("Routing the session...");
+        string operationId = IceUtil::generateUUID();
+        SharedTestData::instance.sessionRouter->routeSession(operationId, session, "102");
+
+        BridgePrx bridge = session->getBridge();
+        BOOST_CHECK(bridge != 0);
+        BOOST_CHECK(SharedTestData::instance.mBridgeConnected);
+
+        // Now transfer to a new extension. In our test mode, this operation will never complete.
+        SharedTestData::instance.sessionRouter->begin_connectBridgedSessionsWithDestination(IceUtil::generateUUID(), session, "103");
+
+        for (int counter=0; SharedTestData::instance.endpointLocator->mLookupCalled == false; counter++)
+        {
+           // Give the main routing service time to do the lookup. 
+            IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(500));
+
+            if (counter > 5)
+            {
+                // Must be other problems!
+                break;
+            }
+        }
+
+        // The lookup should have completed prior to the simulated failure.
+        BOOST_CHECK(SharedTestData::instance.endpointLocator->mLookupCalled);
+
+        // In this test mode, the active routing service will abort after
+        // createing the bridge.
+        BOOST_CHECK(SharedTestData::instance.mBridgeConnected == true);
+
+        // Reset the local flags. 
+        SharedTestData::instance.endpointLocator->mLookupCalled = false;
+        SharedTestData::instance.mBridgeConnected = false;
+
+        // Switch standby component to active. 
+        SharedTestData::instance.serviceReplicaMgmt->activate();
+        BOOST_CHECK(SharedTestData::instance.serviceReplicaMgmt->isActive() == true);
+
+        // Let the backup session router try to route using same operationId. Synchronous call.
+        SharedTestData::instance.backupSessionRouter->routeSession(operationId, session, "103");
+
+        // The lookup should not be done again. 
+        BOOST_CHECK(SharedTestData::instance.endpointLocator->mLookupCalled == false);
+
+        // The bridge shouldn't be created again.
+        BOOST_CHECK(SharedTestData::instance.mBridgeConnected == false);
+
+        // Set the backup back into standby mode.
+        SharedTestData::instance.backupServiceReplicaMgmt->standby();
+        BOOST_CHECK(SharedTestData::instance.backupServiceReplicaMgmt->isActive() == false);
+    }
+    catch (...)
+    {
+        BOOST_FAIL("Exception switching component between active and standby.");
+    }
+
+}

-----------------------------------------------------------------------


-- 
asterisk-scf/integration/routing.git



More information about the asterisk-scf-commits mailing list