[asterisk-scf-commits] asterisk-scf/integration/bridging.git branch "bridge-replication" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Wed Mar 2 07:51:46 CST 2011


branch "bridge-replication" has been updated
       via  648a2edcda7992f8e4e7e72eb5c9f8ce4d0f4d20 (commit)
       via  86832b8c359690a79b152dc657aea9c969379f44 (commit)
       via  a2b836e84227da376985070f22f8a6cc31ec459f (commit)
      from  3a967cb0590297d35cf9fa290512d32bf2423799 (commit)

Summary of changes:
 src/BridgeImpl.cpp        |   42 +++---
 src/ListenerManager.h     |    7 +-
 src/ServiceUtil.h         |    3 +
 src/SessionCollection.cpp |   33 +++--
 src/SessionCollection.h   |   19 ++-
 src/SessionOperations.h   |    8 +-
 src/SessionWrapper.cpp    |    3 -
 test/CMakeLists.txt       |   56 ++++---
 test/TestBridging.cpp     |    8 +
 test/UnitTests.cpp        |  390 +++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 512 insertions(+), 57 deletions(-)
 create mode 100644 test/UnitTests.cpp


- Log -----------------------------------------------------------------
commit 648a2edcda7992f8e4e7e72eb5c9f8ce4d0f4d20
Author: Brent Eagles <beagles at digium.com>
Date:   Wed Mar 2 10:18:23 2011 -0330

    - Added some additional comments.
    - Added more unit tests.
    - Fixed what would end up being a consistency bug in replaceSession.
    - Fixed another unique/shared lock bug.
    - Removed all "automagic" reaping from SessionCollection. It's entirely manual now.
    - SessionCollection::getSessionSeq() now "eat's its own dogfood" and uses
      visitSessions() with a SelectOperation + IfInOperation to select only those
      sessions that are in an "active" state (i.e. not disconnected or marked as
      "Done" for other reasons).

diff --git a/src/BridgeImpl.cpp b/src/BridgeImpl.cpp
index 7267165..61df06c 100644
--- a/src/BridgeImpl.cpp
+++ b/src/BridgeImpl.cpp
@@ -440,26 +440,31 @@ void BridgeImpl::replaceSession(const SessionPrx& oldSession, const SessionSeq&
     statePreCheck();
     
     SessionWrapperPtr session = mSessions->getSession(oldSession);
-    if (session)
+    //
+    // If the session did not exist on this bridge, then this operation should not proceed.
+    //
+    if (!session)
     {
-        try
-        {
-            //
-            // TODO: AMI.
-            //
-            oldSession->removeBridge(mSessionListenerPrx);
-        }
-        catch (const Ice::Exception& ex)
-        {
-            mLogger(Info) << ": removingthe bridge from " << oldSession << " threw " 
-                          << ex.what();
-        }
-        session->disconnect();
-        SessionSeq removed;
-        removed.push_back(oldSession);
-        mListeners->sessionsRemoved(removed);
-        update();
+        throw SessionNotFound(oldSession);
+    }
+    
+    try
+    {
+        //
+        // TODO: AMI.
+        //
+        oldSession->removeBridge(mSessionListenerPrx);
     }
+    catch (const Ice::Exception& ex)
+    {
+        mLogger(Info) << ": removingthe bridge from " << oldSession << " threw " 
+                      << ex.what();
+    }
+    session->disconnect();
+    SessionSeq removed;
+    removed.push_back(oldSession);
+    mListeners->sessionsRemoved(removed);
+    update();
 
     SessionSeq added;
     for (SessionSeq::const_iterator i = newSessions.begin(); i != newSessions.end(); ++i)
@@ -590,7 +595,6 @@ void BridgeImpl::activate()
     mActivated = true;
 }
 
-
 namespace
 {
 class ShutdownThread : public IceUtil::Thread
diff --git a/src/SessionCollection.cpp b/src/SessionCollection.cpp
index cf26a6d..4dac11f 100644
--- a/src/SessionCollection.cpp
+++ b/src/SessionCollection.cpp
@@ -15,6 +15,8 @@
  */
 
 #include "SessionCollection.h"
+#include "SessionOperations.h"
+#include <set>
 
 using namespace AsteriskSCF::System::Logging;
 using namespace AsteriskSCF::SessionCommunications::V1;
@@ -23,7 +25,16 @@ using namespace AsteriskSCF::Bridge::V1;
 using namespace AsteriskSCF;
 using namespace std;
 
-SessionCollection::SessionCollection(const Ice::CommunicatorPtr& comm, const string& bridgeId, const ReplicatorSmartPrx& replicator,
+/**
+ *
+ * NOTE: The lack of reaping throughout is deliberate. Sessions that are in a terminal state are of some interest to the
+ * service internals.  Reaping is consequently a manual process. The visitSessions method + various SessionOperations can
+ * be used to perform state-dependent queries.
+ *
+ **/
+
+SessionCollection::SessionCollection(const Ice::CommunicatorPtr& comm, const string& bridgeId,
+        const ReplicatorSmartPrx& replicator,
         const Logger& logger) :
     mCommunicator(comm),
     mReplicator(replicator),
@@ -104,14 +115,17 @@ bool SessionCollection::hasSession(const SessionPrx& prx)
 
 SessionSeq SessionCollection::getSessionSeq()
 {
-    SessionSeq result;
-    boost::shared_lock<boost::shared_mutex> lock(mLock);
-    reap();
-    for (SessionMap::const_iterator i = mMap.begin(); i != mMap.end(); ++i)
-    {
-        result.push_back(i->second->getSession());
-    }
-    return result;
+    //
+    // TODO: Look at creating some private preinitialized criteria sets so we don't have to initialize this each time.
+    //
+    set<BridgedSessionState> states;
+    states.insert(BridgedSessionState::Added);
+    states.insert(BridgedSessionState::Connected);
+
+    IfInCriteria<set<BridgedSessionState>, StateMemberSelector> active(states);
+    SelectOperation< IfInCriteria<set<BridgedSessionState>, StateMemberSelector>, SessionPrxSelector, SessionSeq>
+        selectIf(active);
+    return visitSessions(selectIf).results();
 }
 
 size_t SessionCollection::size()
@@ -122,7 +136,6 @@ size_t SessionCollection::size()
 
 void SessionCollection::reap()
 {
-    boost::unique_lock<boost::shared_mutex> lock(mLock);
     for (SessionMap::iterator i = mMap.begin(); i != mMap.end();)
     {
         if (i->second->isDestroyed())
diff --git a/src/SessionCollection.h b/src/SessionCollection.h
index 6090a8f..ea3aed0 100644
--- a/src/SessionCollection.h
+++ b/src/SessionCollection.h
@@ -83,22 +83,37 @@ public:
     bool hasSession(const AsteriskSCF::SessionCommunications::V1::SessionPrx& session);
 
     /**
-     * Return a Bridge service compatible sequence of sessions.
+     * Return a Bridge service compatible sequence of sessions. This session sequence does not
+     * include sessions in the collection that are disconnected or awaiting reaping.
      **/
     AsteriskSCF::SessionCommunications::V1::SessionSeq getSessionSeq();
 
+    /**
+     *
+     * Applies the specified operation over the map of sessions.
+     *
+     **/
     template <typename Func>
-    void visitSessions(Func& op)
+    Func& visitSessions(Func& op)
     {
         boost::shared_lock<boost::shared_mutex> lock(mLock);
         for (SessionMap::iterator i = mMap.begin(); i != mMap.end(); ++i)
         {
             op(i->second);
         }
+        return op;
     }
 
+    /**
+     * Return the total number of entries in the collection. Warning: may include sessions that are essentially "done
+     * with". If its desirable to exclude disconnected or "done" sessions, either call reap() beforehand or use the
+     * visitSessions method with a CountIfOperation with an IfInCriteria initialized with the proper values. 
+     **/
     size_t size();
 
+    /**
+     * Release session wrappers for sessions that have reached a terminal state.
+     **/
     void reap();
 
     void replicaUpdate(const AsteriskSCF::Bridge::V1::BridgedSessionPtr& bridgedSession);
diff --git a/test/UnitTests.cpp b/test/UnitTests.cpp
index 41eec40..c57517f 100644
--- a/test/UnitTests.cpp
+++ b/test/UnitTests.cpp
@@ -22,11 +22,13 @@
 #include <AsteriskSCF/Media/MediaIf.h>
 #include <AsteriskSCF/logger.h>
 #include <Ice/Ice.h>
+#include <IceUtil/UUID.h>
 #include <set>
 #include <vector>
 #include <algorithm>
 
 #include "SessionOperations.h"
+#include "SessionCollection.h"
 
 using namespace AsteriskSCF::System::Logging;
 using namespace AsteriskSCF::SessionCommunications::V1;
@@ -34,6 +36,43 @@ using namespace AsteriskSCF::Bridge::V1;
 using namespace AsteriskSCF::BridgeService;
 using namespace std;
 
+class IceEnvironment
+{
+public:
+    IceEnvironment()
+    {
+        //
+        // NOTE: for the moment, the communicator is really a placeholder so doesn't require configuration.
+        //
+        Ice::StringSeq noArgs;
+        mCommunicator = Ice::initialize(noArgs);
+    }
+
+    Ice::CommunicatorPtr communicator()
+    {
+        return mCommunicator;
+    }
+
+    ~IceEnvironment()
+    {
+        try
+        {
+            mCommunicator->destroy();
+        }
+        catch (...)
+        {
+            std::cerr << "exception on destroy!" << std::endl;
+        }
+    }
+
+    Ice::Identity strToIdent(const std::string& s)
+    {
+        return mCommunicator->stringToIdentity(s);
+    }
+
+private:
+    Ice::CommunicatorPtr mCommunicator;
+};
 
 class BridgeIdSelector
 {
@@ -62,6 +101,7 @@ static BridgedSessionPtr createBridgedSession(const BridgedSessionState initialS
 {
     BridgedSessionPtr result(new BridgedSession);
     result->currentState = initialState;
+    result->key = IceUtil::generateUUID();
     return result;
 }
 
@@ -72,6 +112,13 @@ static BridgedSessionPtr createBridgedSession(const BridgedSessionState initialS
     return result;
 }
 
+static BridgedSessionPtr createBridgedSession(const BridgedSessionState initialState, const SessionPrx& proxy)
+{
+    BridgedSessionPtr result(createBridgedSession(initialState));
+    result->session = proxy;
+    return result;
+}
+
 BOOST_AUTO_TEST_SUITE(BridgeUnitTests)
 
 class Fixture
@@ -300,5 +347,44 @@ BOOST_FIXTURE_TEST_CASE(testSelect, Fixture)
     BOOST_CHECK(results[index++] == "b");
 }
 
+BOOST_FIXTURE_TEST_CASE(testGetSeq, Fixture)
+{
+    IceEnvironment iceEnv;
+    AsteriskSCF::BridgeService::ReplicatorSmartPrx rep;
+    SessionCollectionPtr collection(new SessionCollection(iceEnv.communicator(), "test", rep, getLogger()));
+
+    SessionPrx dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo0:default"));
+    collection->replicaUpdate(createBridgedSession(BridgedSessionState::Added, dummy));
+    
+    dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo1:default"));
+    collection->replicaUpdate(createBridgedSession(BridgedSessionState::Added, dummy));
+    
+    dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo2:default"));
+    collection->replicaUpdate(createBridgedSession(BridgedSessionState::Disconnected, dummy));
+    
+    dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo3:default"));
+    collection->replicaUpdate(createBridgedSession(BridgedSessionState::Connected, dummy));
+    
+    dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo4:default"));
+    collection->replicaUpdate(createBridgedSession(BridgedSessionState::Done, dummy));
+    
+    dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo5:default"));
+    collection->replicaUpdate(createBridgedSession(BridgedSessionState::Added, dummy));
+    
+    dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo6:default"));
+    collection->replicaUpdate(createBridgedSession(BridgedSessionState::Disconnected, dummy));
+    
+    dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo7:default"));
+    collection->replicaUpdate(createBridgedSession(BridgedSessionState::Done, dummy));
+    
+    dummy = SessionPrx::uncheckedCast(iceEnv.communicator()->stringToProxy("foo8:default"));
+    collection->replicaUpdate(createBridgedSession(BridgedSessionState::Connected, dummy));
+
+    //
+    // getSessionSeq() should only return the sessions that are *not* disconnected or destroyed.
+    //
+    SessionSeq activeSessions(collection->getSessionSeq());
+    BOOST_CHECK(activeSessions.size() == 5);
+}
 
 BOOST_AUTO_TEST_SUITE_END()

commit 86832b8c359690a79b152dc657aea9c969379f44
Author: Brent Eagles <beagles at digium.com>
Date:   Tue Mar 1 18:47:02 2011 -0330

    Added test for "Select" operations.

diff --git a/test/UnitTests.cpp b/test/UnitTests.cpp
index e4eea61..41eec40 100644
--- a/test/UnitTests.cpp
+++ b/test/UnitTests.cpp
@@ -34,6 +34,24 @@ using namespace AsteriskSCF::Bridge::V1;
 using namespace AsteriskSCF::BridgeService;
 using namespace std;
 
+
+class BridgeIdSelector
+{
+public:
+    BridgeIdSelector(const SessionWrapperPtr& wrapper) :
+        mWrapper(wrapper)
+    {
+    }
+
+    string select()
+    {
+        return mWrapper->getBridgedSession()->bridgeId;
+    }
+
+private:
+    SessionWrapperPtr mWrapper;
+};
+
 /**
  *
  * These tests are "actual" unit tests for verifying that small bits of code within the
@@ -47,6 +65,13 @@ static BridgedSessionPtr createBridgedSession(const BridgedSessionState initialS
     return result;
 }
 
+static BridgedSessionPtr createBridgedSession(const BridgedSessionState initialState, const std::string& bridgeKey)
+{
+    BridgedSessionPtr result(createBridgedSession(initialState));
+    result->bridgeId = bridgeKey;
+    return result;
+}
+
 BOOST_AUTO_TEST_SUITE(BridgeUnitTests)
 
 class Fixture
@@ -171,4 +196,109 @@ BOOST_FIXTURE_TEST_CASE(testCountIf, Fixture)
     BOOST_CHECK((testData.size() -4) == countNegNo.count());
 }
 
+BOOST_FIXTURE_TEST_CASE(testSelect, Fixture)
+{
+   //
+    // Setup some test data.
+    //
+    AsteriskSCF::BridgeService::ReplicatorSmartPrx rep;
+    vector<SessionWrapperPtr> testData;
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Added, "a"), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Added, "b"), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Disconnected, "a"),
+                    rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Connected, "c"), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Done, "a"), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Added, "b"), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Disconnected, "c"), rep,
+                    getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Done, "a"), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Connected, "b"), rep, getLogger()));
+
+    //
+    // Now a variety of test criteria.
+    //
+    IfStateCriteria a(BridgedSessionState::Added);
+    SelectOperation<IfStateCriteria, BridgeIdSelector, vector<string> > selectIf(a);
+    selectIf = for_each(testData.begin(), testData.end(), selectIf);
+    vector<string> results = selectIf.results();
+    BOOST_CHECK(results.size() == 3);
+    int index = 0;
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "b");
+    BOOST_CHECK(results[index++] == "b");
+
+    Negate<IfStateCriteria> notA(a);
+    SelectOperation<Negate<IfStateCriteria>, BridgeIdSelector, vector<string> > selectNotIf(notA);
+    selectNotIf = for_each(testData.begin(), testData.end(), selectNotIf);
+    results = selectNotIf.results();
+    BOOST_CHECK((testData.size() -3) == results.size());
+    index = 0;
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "c");
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "c");
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "b");
+
+    set<BridgedSessionState> yesVals;
+    yesVals.insert(BridgedSessionState::Added);
+    yesVals.insert(BridgedSessionState::Connected);
+    set<BridgedSessionState> noVals;
+    noVals.insert(BridgedSessionState::Disconnected);
+    noVals.insert(BridgedSessionState::Done);
+    
+    IfInCriteria<set<BridgedSessionState>, StateMemberSelector> yes(yesVals);
+    SelectOperation<IfInCriteria<set<BridgedSessionState>, StateMemberSelector>, BridgeIdSelector,
+        vector<string> > selectYes(yes);
+    selectYes = for_each(testData.begin(), testData.end(), selectYes);
+    results = selectYes.results();
+    BOOST_CHECK(results.size() == 5);
+    index = 0;
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "b");
+    BOOST_CHECK(results[index++] == "c");
+    BOOST_CHECK(results[index++] == "b");
+    BOOST_CHECK(results[index++] == "b");
+    
+
+    IfInCriteria<set<BridgedSessionState>, StateMemberSelector> no(noVals);
+    SelectOperation<IfInCriteria<set<BridgedSessionState>, StateMemberSelector>, BridgeIdSelector,
+        vector<string> > selectNo(no);
+    selectNo = for_each(testData.begin(), testData.end(), selectNo);
+    results = selectNo.results();
+    BOOST_CHECK(results.size() == 4);
+    index = 0;
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "c");
+    BOOST_CHECK(results[index++] == "a");
+
+    Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > negYes(yes);
+    SelectOperation<Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> >,
+        BridgeIdSelector, vector<string> > selectNegYes(negYes);
+    selectNegYes = for_each(testData.begin(), testData.end(), selectNegYes);
+    results = selectNegYes.results();
+    BOOST_CHECK((testData.size() -5) == results.size()); 
+    index = 0;
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "c");
+    BOOST_CHECK(results[index++] == "a");
+    
+    Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > negNo(no);
+    SelectOperation<Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > ,
+        BridgeIdSelector, vector<string> > selectNegNo(negNo);
+    selectNegNo = for_each(testData.begin(), testData.end(), selectNegNo);
+    results = selectNegNo.results();
+    BOOST_CHECK((testData.size() -4) == results.size());
+    index = 0;
+    BOOST_CHECK(results[index++] == "a");
+    BOOST_CHECK(results[index++] == "b");
+    BOOST_CHECK(results[index++] == "c");
+    BOOST_CHECK(results[index++] == "b");
+    BOOST_CHECK(results[index++] == "b");
+}
+
+
 BOOST_AUTO_TEST_SUITE_END()

commit a2b836e84227da376985070f22f8a6cc31ec459f
Author: Brent Eagles <beagles at digium.com>
Date:   Tue Mar 1 17:17:22 2011 -0330

    - fix a unique/shared mutex bug ListenerManager
    - add a unit test driver for some small but key code in the bridge service.

diff --git a/src/ListenerManager.h b/src/ListenerManager.h
index e0e8700..c6ef841 100644
--- a/src/ListenerManager.h
+++ b/src/ListenerManager.h
@@ -61,6 +61,11 @@ class ListenerManagerT : public IceUtil::Shared
         }
 
     private:
+        //
+        // NOTE: Currently uses the monitor semantics provided by the Ice threading library. This should be switched to
+        // use a mechanism implemented in Boost if there is something equivalent. (Not indicated as something that needs
+        // to be done, as it really isn't a priority)
+        //
         IceUtil::Monitor<IceUtil::Mutex> mMonitor;
         typename IceUtil::Handle<ListenerManagerT> mMgr;
         bool mStopped;
@@ -182,7 +187,7 @@ protected:
 
     bool init()
     {
-        boost::shared_lock<boost::shared_mutex> lock(mLock);
+        boost::unique_lock<boost::shared_mutex> lock(mLock);
         if(mInitialized)
         {
             return mInitialized;
diff --git a/src/ServiceUtil.h b/src/ServiceUtil.h
index 333d9d2..36610b9 100644
--- a/src/ServiceUtil.h
+++ b/src/ServiceUtil.h
@@ -77,6 +77,9 @@ public:
 
 private:
 
+    //
+    // TODO: boost?
+    //
     IceUtil::Mutex mLock;
     Ice::CommunicatorPtr mCommunicator;
     std::string mProxyString;
diff --git a/src/SessionOperations.h b/src/SessionOperations.h
index 9648553..d08d9cd 100644
--- a/src/SessionOperations.h
+++ b/src/SessionOperations.h
@@ -139,7 +139,8 @@ class CountIfOperation : public std::unary_function<SessionWrapperPtr, void>
 {
 public:
     CountIfOperation(const Crit& crit) :
-        mCriteria(crit)
+        mCriteria(crit),
+        mCount(0)
     {
     }
     
@@ -151,7 +152,10 @@ public:
         }
     }
     
-    size_t count() const;
+    size_t count() const
+    {
+        return mCount;
+    }
 private:
     Crit mCriteria;
     size_t mCount;
diff --git a/src/SessionWrapper.cpp b/src/SessionWrapper.cpp
index aa75ace..67d03ba 100644
--- a/src/SessionWrapper.cpp
+++ b/src/SessionWrapper.cpp
@@ -116,9 +116,6 @@ void SessionWrapper::update(const BridgedSessionPtr& update)
 
 void SessionWrapper::pushUpdate()
 {
-    // XXX this might be redundnant.
-    mLogger(Debug) << ": replicating and update for " << mSession->key;
-
     boost::unique_lock<boost::shared_mutex> lock(mLock);
     ++mSession->serial;
     ReplicatedStateItemSeq seq;
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 80e2a80..4b34369 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -2,24 +2,24 @@ asterisk_scf_slice_include_directories(${API_SLICE_DIR})
 if(NOT integrated_build STREQUAL "true")
   add_subdirectory(channel_driver/local_slice)
 endif()
-asterisk_scf_component_init(bridging_unit_test CXX)
+asterisk_scf_component_init(bridge_component_test CXX)
 include_directories("../src")
 include_directories(${utils_dir}/SmartProxy/include)
-asterisk_scf_component_add_slice(bridging_unit_test CommandsIf)
-asterisk_scf_component_add_file(bridging_unit_test TestBridging.cpp)
-asterisk_scf_component_add_file(bridging_unit_test SessionListenerI.h)
-asterisk_scf_component_add_file(bridging_unit_test SessionListenerI.cpp)
-asterisk_scf_component_add_file(bridging_unit_test BridgeListenerI.h)
-asterisk_scf_component_add_file(bridging_unit_test BridgeListenerI.cpp)
-asterisk_scf_component_add_file(bridging_unit_test BridgeManagerListenerI.h)
-asterisk_scf_component_add_file(bridging_unit_test BridgeManagerListenerI.cpp)
-asterisk_scf_component_add_file(bridging_unit_test TestCommandDriver.cpp)
-asterisk_scf_component_add_file(bridging_unit_test TestCommandDriver.h)
-asterisk_scf_component_add_slice(bridging_unit_test ../src/BridgeReplicatorIf.ice)
+asterisk_scf_component_add_slice(bridge_component_test CommandsIf)
+asterisk_scf_component_add_file(bridge_component_test TestBridging.cpp)
+asterisk_scf_component_add_file(bridge_component_test SessionListenerI.h)
+asterisk_scf_component_add_file(bridge_component_test SessionListenerI.cpp)
+asterisk_scf_component_add_file(bridge_component_test BridgeListenerI.h)
+asterisk_scf_component_add_file(bridge_component_test BridgeListenerI.cpp)
+asterisk_scf_component_add_file(bridge_component_test BridgeManagerListenerI.h)
+asterisk_scf_component_add_file(bridge_component_test BridgeManagerListenerI.cpp)
+asterisk_scf_component_add_file(bridge_component_test TestCommandDriver.cpp)
+asterisk_scf_component_add_file(bridge_component_test TestCommandDriver.h)
+asterisk_scf_component_add_slice(bridge_component_test ../src/BridgeReplicatorIf.ice)
 
-asterisk_scf_component_add_ice_libraries(bridging_unit_test IceStorm)
-asterisk_scf_component_add_ice_libraries(bridging_unit_test IceBox)
-asterisk_scf_component_add_boost_libraries(bridging_unit_test unit_test_framework thread)
+asterisk_scf_component_add_ice_libraries(bridge_component_test IceStorm)
+asterisk_scf_component_add_ice_libraries(bridge_component_test IceBox)
+asterisk_scf_component_add_boost_libraries(bridge_component_test unit_test_framework thread)
 
 if(NOT logger_dir)
    message(FATAL_ERROR "The logger directory could not be found ${logger_dir}")
@@ -29,12 +29,28 @@ include_directories(${API_INCLUDE_DIR})
 if(integrated_build STREQUAL "true")
    include_directories(${CMAKE_CURRENT_BINARY_DIR}/../../test_channel/local_slice/generated)
 endif()
-asterisk_scf_component_build_icebox(bridging_unit_test)
-target_link_libraries(bridging_unit_test logging-client)
-target_link_libraries(bridging_unit_test asterisk-scf-api)
-target_link_libraries(bridging_unit_test test-channel-api)
+asterisk_scf_component_build_icebox(bridge_component_test)
+target_link_libraries(bridge_component_test logging-client)
+target_link_libraries(bridge_component_test asterisk-scf-api)
+target_link_libraries(bridge_component_test test-channel-api)
 
 # component tests only work for integrated builds
 if(integrated_build STREQUAL "true")
-  icebox_add_test(bridging_unit_test ../config/test_bridging.conf)
+  icebox_add_test(bridge_component_test ../config/test_bridging.conf)
 endif()
+
+asterisk_scf_component_init(bridge_unit_tests CXX)
+asterisk_scf_component_add_slice(bridge_unit_tests ../src/BridgeReplicatorIf.ice)
+asterisk_scf_component_add_file(bridge_unit_tests ../src/SessionCollection.cpp)
+asterisk_scf_component_add_file(bridge_unit_tests ../src/SessionOperations.cpp)
+asterisk_scf_component_add_file(bridge_unit_tests ../src/SessionWrapper.cpp)
+asterisk_scf_component_add_file(bridge_unit_tests ../src/MediaSplicer.cpp)
+asterisk_scf_component_add_file(bridge_unit_tests UnitTests.cpp)
+asterisk_scf_component_add_ice_libraries(bridge_component_test Ice)
+asterisk_scf_component_add_boost_libraries(bridge_unit_tests unit_test_framework thread)
+asterisk_scf_component_build_standalone(bridge_unit_tests)
+
+target_link_libraries(bridge_unit_tests logging-client)
+target_link_libraries(bridge_unit_tests asterisk-scf-api)
+
+
diff --git a/test/TestBridging.cpp b/test/TestBridging.cpp
index 3fc4510..e1ba7b2 100644
--- a/test/TestBridging.cpp
+++ b/test/TestBridging.cpp
@@ -50,6 +50,11 @@ public:
         mArgs(args),
         mArgv(0)
     {
+        //
+        // TODO: stl ensures that a std::vector's memory organization is compatible with
+        // casting to C pointers, so this should be converted to take advantage of that.
+        // (see the other test suites).
+        //
         const char* fakeName = "BRIDGE_TEST_SERVICE";
         mArgc = args.size() + 1;
         mArgv = new char*[mArgc];
@@ -109,6 +114,9 @@ typedef IceUtil::Handle<TestEnvironment> TestEnvironmentPtr;
 //
 TestEnvironmentPtr globalTestEnvironment;
 
+//
+// Simple helper for initializing Ice and ensuring proper cleanup in the context of a test case.
+//
 class IceEnvironment
 {
 public:
diff --git a/test/UnitTests.cpp b/test/UnitTests.cpp
new file mode 100644
index 0000000..e4eea61
--- /dev/null
+++ b/test/UnitTests.cpp
@@ -0,0 +1,174 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010, Digium, Inc.
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk SCF project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE.txt file
+ * at the top of the source tree.
+ */
+
+#define BOOST_TEST_MODULE "Bridge internals unit test"
+#include <boost/test/unit_test.hpp>
+#include <boost/bind.hpp>
+#include <boost/test/debug.hpp>
+#include <AsteriskSCF/SessionCommunications/SessionCommunicationsIf.h>
+#include <AsteriskSCF/Media/MediaIf.h>
+#include <AsteriskSCF/logger.h>
+#include <Ice/Ice.h>
+#include <set>
+#include <vector>
+#include <algorithm>
+
+#include "SessionOperations.h"
+
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::SessionCommunications::V1;
+using namespace AsteriskSCF::Bridge::V1;
+using namespace AsteriskSCF::BridgeService;
+using namespace std;
+
+/**
+ *
+ * These tests are "actual" unit tests for verifying that small bits of code within the
+ * bridging service are working properly.
+ *
+ **/
+static BridgedSessionPtr createBridgedSession(const BridgedSessionState initialState)
+{
+    BridgedSessionPtr result(new BridgedSession);
+    result->currentState = initialState;
+    return result;
+}
+
+BOOST_AUTO_TEST_SUITE(BridgeUnitTests)
+
+class Fixture
+{
+public:
+    Fixture() :
+        mLogger(getLoggerFactory().getLogger("AsteriskSCF.BridgeUnitTests"))
+    {
+    }
+
+    ~Fixture()
+    {
+    }
+
+    Logger getLogger()
+    {
+        return mLogger;
+    }
+private:
+    Logger mLogger;
+};
+
+BOOST_FIXTURE_TEST_CASE(testIfState, Fixture)
+{
+    BridgedSessionPtr letter(createBridgedSession(BridgedSessionState::Added));
+    SessionWrapperPtr wrapper(new SessionWrapper(letter, AsteriskSCF::BridgeService::ReplicatorSmartPrx(), getLogger()));
+    IfStateCriteria a(BridgedSessionState::Added);
+    IfStateCriteria b(BridgedSessionState::Connected);
+    BOOST_CHECK(a(wrapper));
+    BOOST_CHECK(!b(wrapper));
+}
+
+BOOST_FIXTURE_TEST_CASE(testIfInCrriteria, Fixture)
+{
+    BridgedSessionPtr letter(createBridgedSession(BridgedSessionState::Added));
+    SessionWrapperPtr wrapper(new SessionWrapper(letter, AsteriskSCF::BridgeService::ReplicatorSmartPrx(), getLogger()));
+    set<BridgedSessionState> yesVals;
+    yesVals.insert(BridgedSessionState::Added);
+    yesVals.insert(BridgedSessionState::Connected);
+    set<BridgedSessionState> noVals;
+    noVals.insert(BridgedSessionState::Disconnected);
+    noVals.insert(BridgedSessionState::Done);
+    IfInCriteria<set<BridgedSessionState>, StateMemberSelector> yes(yesVals);
+    IfInCriteria<set<BridgedSessionState>, StateMemberSelector> no(noVals);
+    BOOST_CHECK(yes(wrapper));
+    BOOST_CHECK(!no(wrapper));
+}
+
+BOOST_FIXTURE_TEST_CASE(testNegation, Fixture)
+{
+    BridgedSessionPtr letter(createBridgedSession(BridgedSessionState::Added));
+    SessionWrapperPtr wrapper(new SessionWrapper(letter, AsteriskSCF::BridgeService::ReplicatorSmartPrx(), getLogger()));
+    set<BridgedSessionState> yesVals;
+    yesVals.insert(BridgedSessionState::Added);
+    yesVals.insert(BridgedSessionState::Connected);
+    set<BridgedSessionState> noVals;
+    noVals.insert(BridgedSessionState::Disconnected);
+    noVals.insert(BridgedSessionState::Done);
+    IfInCriteria<set<BridgedSessionState>, StateMemberSelector> yes(yesVals);
+    IfInCriteria<set<BridgedSessionState>, StateMemberSelector> no(noVals);
+    Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > negYes(yes);
+    Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > negNo(no);
+    
+    BOOST_CHECK(!negYes(wrapper));
+    BOOST_CHECK(negNo(wrapper));
+}
+
+BOOST_FIXTURE_TEST_CASE(testCountIf, Fixture)
+{
+    //
+    // Setup some test data.
+    //
+    AsteriskSCF::BridgeService::ReplicatorSmartPrx rep;
+    vector<SessionWrapperPtr> testData;
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Added), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Added), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Disconnected), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Connected), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Done), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Added), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Disconnected), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Done), rep, getLogger()));
+    testData.push_back(new SessionWrapper(createBridgedSession(BridgedSessionState::Connected), rep, getLogger()));
+
+    //
+    // Now a variety of test criteria.
+    //
+    IfStateCriteria a(BridgedSessionState::Added);
+    CountIfOperation<IfStateCriteria> countIf(a);
+    countIf = for_each(testData.begin(), testData.end(), countIf);
+    BOOST_CHECK(countIf.count() == 3);
+
+    Negate<IfStateCriteria> notA(a);
+    CountIfOperation<Negate<IfStateCriteria> > countNotIf(notA);
+    countNotIf = for_each(testData.begin(), testData.end(), countNotIf);
+    BOOST_CHECK((testData.size() -3) == countNotIf.count());
+
+    set<BridgedSessionState> yesVals;
+    yesVals.insert(BridgedSessionState::Added);
+    yesVals.insert(BridgedSessionState::Connected);
+    set<BridgedSessionState> noVals;
+    noVals.insert(BridgedSessionState::Disconnected);
+    noVals.insert(BridgedSessionState::Done);
+    IfInCriteria<set<BridgedSessionState>, StateMemberSelector> yes(yesVals);
+    CountIfOperation<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > countYes(yes);
+    countYes = for_each(testData.begin(), testData.end(), countYes);
+    BOOST_CHECK(countYes.count() == 5);
+
+    IfInCriteria<set<BridgedSessionState>, StateMemberSelector> no(noVals);
+    CountIfOperation<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > countNo(no);
+    countNo = for_each(testData.begin(), testData.end(), countNo);
+    BOOST_CHECK(countNo.count() == 4);
+
+    Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > negYes(yes);
+    CountIfOperation<Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > > countNegYes(negYes);
+    countNegYes = for_each(testData.begin(), testData.end(), countNegYes);
+    BOOST_CHECK((testData.size() -5) == countNegYes.count()); 
+
+    Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > negNo(no);
+    CountIfOperation<Negate<IfInCriteria<set<BridgedSessionState>, StateMemberSelector> > > countNegNo(negNo);
+    countNegNo = for_each(testData.begin(), testData.end(), countNegNo);
+    BOOST_CHECK((testData.size() -4) == countNegNo.count());
+}
+
+BOOST_AUTO_TEST_SUITE_END()

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


-- 
asterisk-scf/integration/bridging.git



More information about the asterisk-scf-commits mailing list