[asterisk-scf-commits] asterisk-scf/integration/media_operations_core.git branch "retry_deux" updated.

Commits to the Asterisk SCF project code repositories asterisk-scf-commits at lists.digium.com
Mon Mar 19 19:23:20 CDT 2012


branch "retry_deux" has been updated
       via  1d23331df6c10c92fa72e11e911acaa16a626bdd (commit)
      from  f2777b25d2078ab0f82152aa19c7dbb30e7c21c3 (commit)

Summary of changes:
 src/InbandTelephonyEvents.cpp                 |    3 -
 src/MediaOperationFactoryImpl.h               |    8 ++-
 src/MediaOperationStateReplicator.h           |    6 +-
 src/MediaOperationStateReplicatorListener.cpp |   24 ++++++-
 src/TranslatorOperationFactory.cpp            |   82 ++++++++++++++++---------
 src/TranslatorOperationFactory.h              |    5 ++
 src/TranslatorSink.cpp                        |   11 +++-
 src/TranslatorSink.h                          |    5 +-
 src/TranslatorSource.cpp                      |   28 +++++++--
 src/TranslatorSource.h                        |   13 +++--
 test/TestMediaOperations.cpp                  |   66 +++++++++++++++++++-
 11 files changed, 197 insertions(+), 54 deletions(-)


- Log -----------------------------------------------------------------
commit 1d23331df6c10c92fa72e11e911acaa16a626bdd
Author: David M. Lee <dlee at digium.com>
Date:   Mon Mar 19 19:22:54 2012 -0500

    Retry logic + unit tests.

diff --git a/src/InbandTelephonyEvents.cpp b/src/InbandTelephonyEvents.cpp
index c02097f..5b5524a 100644
--- a/src/InbandTelephonyEvents.cpp
+++ b/src/InbandTelephonyEvents.cpp
@@ -54,9 +54,6 @@ private:
     const std::string mFormatName;
 };
 
-typedef ValueOperationContextCookie<MediaOperationPrx> CreateMediaOperationCookie;
-typedef boost::shared_ptr<CreateMediaOperationCookie> CreateMediaOperationCookiePtr;
-
 } // anonymous namespace
 
 namespace AsteriskSCF
diff --git a/src/MediaOperationFactoryImpl.h b/src/MediaOperationFactoryImpl.h
index 53089aa..61715bd 100644
--- a/src/MediaOperationFactoryImpl.h
+++ b/src/MediaOperationFactoryImpl.h
@@ -17,9 +17,11 @@
 #pragma once
 
 #include <Ice/Ice.h>
-#include <AsteriskSCF/Media/MediaOperationIf.h>
+
 #include <AsteriskSCF/Core/Discovery/ServiceLocatorIf.h>
 #include <AsteriskSCF/Logger.h>
+#include <AsteriskSCF/Media/MediaOperationIf.h>
+#include <AsteriskSCF/Operations/OperationContextCache.h>
 
 #include "MediaOperationReplicationContext.h"
 
@@ -71,5 +73,9 @@ protected:
 
 typedef IceUtil::Handle<MediaOperationFactoryImpl> MediaOperationFactoryImplPtr;
 
+// Implementations typically need this as the cookie for the createMediaOperation
+typedef Operations::ValueOperationContextCookie<AsteriskSCF::Media::V1::MediaOperationPrx> CreateMediaOperationCookie;
+typedef boost::shared_ptr<CreateMediaOperationCookie> CreateMediaOperationCookiePtr;
+
 } //end namespace MediaOperationsCore
 } //end namespace AsteriskSCF
diff --git a/src/MediaOperationStateReplicator.h b/src/MediaOperationStateReplicator.h
index e64669d..4260cbe 100644
--- a/src/MediaOperationStateReplicator.h
+++ b/src/MediaOperationStateReplicator.h
@@ -16,8 +16,9 @@
 
 #pragma once
 
-#include <AsteriskSCF/Replication/StateReplicator.h>
+#include <AsteriskSCF/Operations/OperationContextCache.h>
 #include <AsteriskSCF/Replication/MediaOperationsCore/MediaOperationsCoreIf.h>
+#include <AsteriskSCF/Replication/StateReplicator.h>
 
 namespace AsteriskSCF
 {
@@ -40,6 +41,7 @@ public:
     void stateRemovedForItems(const AsteriskSCF::System::V1::OperationContextPtr&, const AsteriskSCF::Replication::MediaOperationsCore::V1::MediaOperationStateItemSeq&, const Ice::Current&);
     void stateSet(const AsteriskSCF::System::V1::OperationContextPtr&, const AsteriskSCF::Replication::MediaOperationsCore::V1::MediaOperationStateItemSeq&, const Ice::Current&);
 private:
+    Operations::OperationContextCachePtr mOperationContextCache;
     /**
      * Note this is the "service" object adapter, and not the "backplane"
      * adapter used for state replication.
@@ -47,7 +49,7 @@ private:
      * We need this adapter in the state replication listener so that
      * services can be added and removed as appropriate.
      */
-    Ice::ObjectAdapterPtr mAdapter;
+    const Ice::ObjectAdapterPtr mAdapter;
 };
 
 typedef IceUtil::Handle<MediaOperationStateReplicatorListenerImpl> MediaOperationStateReplicatorListenerImplPtr;
diff --git a/src/MediaOperationStateReplicatorListener.cpp b/src/MediaOperationStateReplicatorListener.cpp
index 9eb510c..166af78 100644
--- a/src/MediaOperationStateReplicatorListener.cpp
+++ b/src/MediaOperationStateReplicatorListener.cpp
@@ -29,8 +29,10 @@ namespace MediaOperationsCore
 
 using namespace AsteriskSCF::Replication::MediaOperationsCore::V1;
 
+const int TTL_SECONDS = 180;
+
 MediaOperationStateReplicatorListenerImpl::MediaOperationStateReplicatorListenerImpl(const Ice::ObjectAdapterPtr& adapter)
-    : mAdapter(adapter)
+    : mOperationContextCache(Operations::OperationContextCache::create(TTL_SECONDS)), mAdapter(adapter)
 {
 }
 
@@ -43,10 +45,18 @@ void MediaOperationStateReplicatorListenerImpl::stateRemoved(
 }
 
 void MediaOperationStateReplicatorListenerImpl::stateRemovedForItems(
-        const AsteriskSCF::System::V1::OperationContextPtr&,
+        const AsteriskSCF::System::V1::OperationContextPtr& operationContext,
         const MediaOperationStateItemSeq& items,
         const Ice::Current&)
 {
+    // mAdapter is constant; mOperationContextCache is thread safe
+    // no further locking needed
+    if (!mOperationContextCache->addOperationContext(operationContext))
+    {
+        // repeated execution; ignore
+        return;
+    }
+
     class Visitor : public MediaOperationStateItemVisitor
     {
     public:
@@ -82,10 +92,18 @@ void MediaOperationStateReplicatorListenerImpl::stateRemovedForItems(
 }
 
 void MediaOperationStateReplicatorListenerImpl::stateSet(
-        const AsteriskSCF::System::V1::OperationContextPtr&,
+        const AsteriskSCF::System::V1::OperationContextPtr& operationContext,
         const MediaOperationStateItemSeq& items,
         const Ice::Current&)
 {
+    // mAdapter is constant; mOperationContextCache is thread safe
+    // no further locking needed
+    if (!mOperationContextCache->addOperationContext(operationContext))
+    {
+        // repeated execution; ignore
+        return;
+    }
+
     class Visitor : public MediaOperationStateItemVisitor
     {
     public:
diff --git a/src/TranslatorOperationFactory.cpp b/src/TranslatorOperationFactory.cpp
index efe97d4..504c4ce 100644
--- a/src/TranslatorOperationFactory.cpp
+++ b/src/TranslatorOperationFactory.cpp
@@ -26,13 +26,17 @@ namespace MediaOperationsCore
 
 using namespace AsteriskSCF::Media::V1;
 using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::Operations;
+
+const int TTL_SECONDS = 180;
 
 TranslatorOperationFactory::TranslatorOperationFactory(
         const Ice::ObjectAdapterPtr& adapter,
         const Logger& logger,
         const MediaOperationReplicationContextPtr& replicationContext,
         const std::string& name)
-    : MediaOperationFactoryImpl(adapter, logger, replicationContext, name)
+    : MediaOperationFactoryImpl(adapter, logger, replicationContext, name),
+      mOperationContextCache(Operations::OperationContextCache::create(TTL_SECONDS))
 {
     mLocatorParams->category = MediaOperationDiscoveryCategory;
     mLocatorParams->service = MediaOperationDiscoveryTranslatorService;
@@ -41,59 +45,80 @@ TranslatorOperationFactory::TranslatorOperationFactory(
 TranslatorOperationFactory::~TranslatorOperationFactory() { }
 
 MediaOperationPrx TranslatorOperationFactory::createMediaOperation(
-        const AsteriskSCF::System::V1::OperationContextPtr&,
+        const AsteriskSCF::System::V1::OperationContextPtr& operationContext,
         const StreamSourcePrx& source,
         const StreamSinkPrx& sink,
         const Ice::Current&)
 {
-    if (sink == 0 || source == 0)
+    boost::shared_lock<boost::shared_mutex> lock(mMutex);
+    const CreateMediaOperationCookiePtr cookie(new CreateMediaOperationCookie);
+    OperationContextCookiePtr existingCookie;
+    mOperationContextCache->addOperationContext(operationContext, cookie, existingCookie);
+
+    if (existingCookie)
     {
-        mLogger(Error) << "Cannot create translator because of a missing source or sink";
-        throw UnsupportedMediaFormatException();
+        CreateMediaOperationCookiePtr c = boost::dynamic_pointer_cast<CreateMediaOperationCookie>(existingCookie);
+        return c->get();
     }
 
-    FormatSeq sourceFormats = source->getFormats();
-    FormatSeq sinkFormats = sink->getFormats();
+    try
+    {
+        if (sink == 0 || source == 0)
+        {
+            mLogger(Error) << "Cannot create translator because of a missing source or sink";
+            throw UnsupportedMediaFormatException();
+        }
+
+        FormatSeq sourceFormats = source->getFormats();
+        FormatSeq sinkFormats = sink->getFormats();
 
-    FormatSeq::iterator supportedInput = std::find_first_of(sourceFormats.begin(),
+        FormatSeq::iterator supportedInput = std::find_first_of(sourceFormats.begin(),
             sourceFormats.end(),
             mTranslations.begin(),
             mTranslations.end(),
             TranslatorOperationFactory::formatsEqualMap);
 
-    if (supportedInput == sourceFormats.end())
-    {
-        mLogger(Error) << "Cannot create translator because none of the stream source's formats are supported";
-        throw UnsupportedMediaFormatException();
-    }
+        if (supportedInput == sourceFormats.end())
+        {
+            mLogger(Error) << "Cannot create translator because none of the stream source's formats are supported";
+            throw UnsupportedMediaFormatException();
+        }
 
-    mLogger(Debug) << "When creating media operation, the input is " << (*supportedInput)->name;
+        mLogger(Debug) << "When creating media operation, the input is " << (*supportedInput)->name;
 
-    for (FormatSeq::iterator iter = mTranslations[(*supportedInput)->name].begin();
-            iter != mTranslations[(*supportedInput)->name].end(); ++iter)
-    {
-        mLogger(Debug) << (*supportedInput)->name << " can be translated to " << (*iter)->name;
-    }
+        for (FormatSeq::iterator iter = mTranslations[(*supportedInput)->name].begin();
+             iter != mTranslations[(*supportedInput)->name].end(); ++iter)
+        {
+            mLogger(Debug) << (*supportedInput)->name << " can be translated to " << (*iter)->name;
+        }
 
-    FormatSeq::iterator supportedOutput = std::find_first_of(sinkFormats.begin(),
+        FormatSeq::iterator supportedOutput = std::find_first_of(sinkFormats.begin(),
             sinkFormats.end(),
             mTranslations[(*supportedInput)->name].begin(),
             mTranslations[(*supportedInput)->name].end(),
             TranslatorOperationFactory::formatsEqual);
 
-    if (supportedOutput == sinkFormats.end())
-    {
-        mLogger(Error) << "Cannot create translator because none of the stream sink's formats are supported";
-        throw UnsupportedMediaFormatException();
-    }
+        if (supportedOutput == sinkFormats.end())
+        {
+            mLogger(Error) << "Cannot create translator because none of the stream sink's formats are supported";
+            throw UnsupportedMediaFormatException();
+        }
 
-    mLogger(Debug) << "Creating a translator from " << (*supportedInput)->name
-        << " to " << (*supportedOutput)->name;
+        mLogger(Debug) << "Creating a translator from " << (*supportedInput)->name
+                       << " to " << (*supportedOutput)->name;
 
-    return createMediaOperation(
+        MediaOperationPrx r =  createMediaOperation(
             *supportedOutput,
             *supportedInput,
             IceUtil::generateUUID());
+        cookie->set(r);
+        return r;
+    }
+    catch (const Ice::Exception& e)
+    {
+        cookie->setException(e);
+        throw;
+    }
 }
 
 void TranslatorOperationFactory::addTranslation(
@@ -101,6 +126,7 @@ void TranslatorOperationFactory::addTranslation(
         const FormatPtr& outFormat,
         int cost)
 {
+    boost::unique_lock<boost::shared_mutex> lock(mMutex);
     mTranslations[inFormat->name].push_back(outFormat);
 
     MediaOperationAttributes attrs;
diff --git a/src/TranslatorOperationFactory.h b/src/TranslatorOperationFactory.h
index 9dd1562..e887f84 100644
--- a/src/TranslatorOperationFactory.h
+++ b/src/TranslatorOperationFactory.h
@@ -18,6 +18,9 @@
 
 #include "MediaOperationFactoryImpl.h"
 
+#include <AsteriskSCF/Operations/OperationContextCache.h>
+#include <boost/thread.hpp>
+
 namespace AsteriskSCF
 {
 
@@ -99,6 +102,8 @@ private:
             const AsteriskSCF::Media::V1::FormatPtr& lhs,
             const std::pair<std::string, AsteriskSCF::Media::V1::FormatSeq>& rhs);
 
+    boost::shared_mutex mMutex;
+    Operations::OperationContextCachePtr mOperationContextCache;
     TranslationMap mTranslations;
 };
 
diff --git a/src/TranslatorSink.cpp b/src/TranslatorSink.cpp
index 343e7e3..8b56b5b 100644
--- a/src/TranslatorSink.cpp
+++ b/src/TranslatorSink.cpp
@@ -37,37 +37,44 @@ TranslatorSink::TranslatorSink(const Logger& logger,
 
 TranslatorSink::~TranslatorSink()
 {
-    mLogger(Debug) << "TranslatorSink destructor called";
+    mLogger(Trace) << "TranslatorSink destructor called";
 }
 
 void TranslatorSink::write(const FrameSeq& frames, const Ice::Current&)
 {
+    boost::shared_lock<boost::shared_mutex> lock(mMutex);
     mTranslator->translateFrames(frames);
 }
 
 void TranslatorSink::setTranslator(const TranslatorPtr& translator)
 {
+    boost::unique_lock<boost::shared_mutex> lock(mMutex);
     mTranslator = translator;
 }
 
-void TranslatorSink::setSource(const AsteriskSCF::System::V1::OperationContextPtr&, 
+void TranslatorSink::setSource(const AsteriskSCF::System::V1::OperationContextPtr&,
     const StreamSourcePrx& source, const Ice::Current&)
 {
+    boost::unique_lock<boost::shared_mutex> lock(mMutex);
+    // naturally idempotent - multiple sets are harmless
     mSource = source;
 }
 
 StreamSourcePrx TranslatorSink::getSource(const Ice::Current&)
 {
+    boost::shared_lock<boost::shared_mutex> lock(mMutex);
     return mSource;
 }
 
 FormatSeq TranslatorSink::getFormats(const Ice::Current&)
 {
+    boost::shared_lock<boost::shared_mutex> lock(mMutex);
     return mSupportedFormats;
 }
 
 std::string TranslatorSink::getId(const Ice::Current&)
 {
+    // constant; no need to lock
     return mId;
 }
 
diff --git a/src/TranslatorSink.h b/src/TranslatorSink.h
index 5c0ea17..7b16868 100644
--- a/src/TranslatorSink.h
+++ b/src/TranslatorSink.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <boost/thread.hpp>
+
 #include <AsteriskSCF/Media/MediaIf.h>
 #include <AsteriskSCF/Logger.h>
 
@@ -50,10 +52,11 @@ public:
     std::string getId(const Ice::Current&);
 
 private:
+    boost::shared_mutex mMutex;
     AsteriskSCF::System::Logging::Logger mLogger;
     AsteriskSCF::Media::V1::FormatSeq mSupportedFormats;
     AsteriskSCF::Media::V1::StreamSourcePrx mSource;
-    std::string mId;
+    const std::string mId;
     TranslatorPtr mTranslator;
 };
 
diff --git a/src/TranslatorSource.cpp b/src/TranslatorSource.cpp
index 8999416..08c6053 100644
--- a/src/TranslatorSource.cpp
+++ b/src/TranslatorSource.cpp
@@ -36,45 +36,53 @@ TranslatorSource::TranslatorSource(const Logger& logger,
 
 TranslatorSource::~TranslatorSource()
 {
-    mLogger(Debug) << "TranslatorSource destructor called";
+    mLogger(Trace) << "TranslatorSource destructor called";
 }
 
-void TranslatorSource::addSink(const AsteriskSCF::System::V1::OperationContextPtr&, 
+void TranslatorSource::addSink(const AsteriskSCF::System::V1::OperationContextPtr&,
     const StreamSinkPrx& sink, const Ice::Current&)
 {
+    boost::unique_lock<boost::shared_mutex> lock(mMutex);
+    // naturally idempotent - multiple adds are harmless
     if (std::find(mSinks.begin(), mSinks.end(), sink) == mSinks.end())
     {
         mSinks.push_back(sink);
     }
 }
 
-void TranslatorSource::removeSink(const AsteriskSCF::System::V1::OperationContextPtr&, 
+void TranslatorSource::removeSink(const AsteriskSCF::System::V1::OperationContextPtr&,
     const StreamSinkPrx& sink, const Ice::Current&)
 {
+    boost::unique_lock<boost::shared_mutex> lock(mMutex);
+    // naturally idempotent - multiple removes are harmless
     mSinks.erase(std::remove(mSinks.begin(), mSinks.end(), sink), mSinks.end());
 }
 
 StreamSinkSeq TranslatorSource::getSinks(const Ice::Current&)
 {
+    boost::shared_lock<boost::shared_mutex> lock(mMutex);
     return mSinks;
 }
 
 FormatSeq TranslatorSource::getFormats(const Ice::Current&)
 {
+    // mSupportedFormats never changes after construction; no lock needed
     return mSupportedFormats;
 }
 
 std::string TranslatorSource::getId(const Ice::Current&)
 {
+    // mId contant; no lock needed
     return mId;
 }
 
 //XXX
 //I interpreted this to essentially be a check to make sure that
 //the format we actually are using matches what is expected.
-void TranslatorSource::requestFormat(const AsteriskSCF::System::V1::OperationContextPtr&, 
+void TranslatorSource::requestFormat(const AsteriskSCF::System::V1::OperationContextPtr&,
     const FormatPtr& format, const Ice::Current&)
 {
+    // mSupportedFormats never changes after construction; no lock needed
     FormatPtr supportedFormat = mSupportedFormats.front();
 
     if (supportedFormat->name != format->name)
@@ -86,8 +94,16 @@ void TranslatorSource::requestFormat(const AsteriskSCF::System::V1::OperationCon
 
 void TranslatorSource::distributeToSinks(const FrameSeq& translatedFrames)
 {
-    for (StreamSinkSeq::iterator iter = mSinks.begin();
-            iter != mSinks.end(); ++iter)
+    // it's unwise to invoke remote operations while holding a mutex.
+    // copy the sink list while holding the mutex, then use the copy.
+    StreamSinkSeq sinks;
+    {
+        boost::shared_lock<boost::shared_mutex> lock(mMutex);
+        sinks = mSinks;
+    }
+
+    for (StreamSinkSeq::iterator iter = sinks.begin();
+            iter != sinks.end(); ++iter)
     {
         try
         {
diff --git a/src/TranslatorSource.h b/src/TranslatorSource.h
index f4ebd6b..f9ae1c5 100644
--- a/src/TranslatorSource.h
+++ b/src/TranslatorSource.h
@@ -16,6 +16,8 @@
 
 #pragma once
 
+#include <boost/thread.hpp>
+
 #include <AsteriskSCF/Media/MediaIf.h>
 #include <AsteriskSCF/Logger.h>
 
@@ -33,12 +35,12 @@ public:
 
     ~TranslatorSource();
 
-    void addSink(const AsteriskSCF::System::V1::OperationContextPtr&, 
+    void addSink(const AsteriskSCF::System::V1::OperationContextPtr&,
         const AsteriskSCF::Media::V1::StreamSinkPrx& sink, const Ice::Current&);
-    
-    void removeSink(const AsteriskSCF::System::V1::OperationContextPtr&, 
+
+    void removeSink(const AsteriskSCF::System::V1::OperationContextPtr&,
         const AsteriskSCF::Media::V1::StreamSinkPrx& sink, const Ice::Current&);
-    
+
     AsteriskSCF::Media::V1::StreamSinkSeq getSinks(const Ice::Current&);
 
     AsteriskSCF::Media::V1::FormatSeq getFormats(const Ice::Current&);
@@ -51,10 +53,11 @@ public:
     void distributeToSinks(const AsteriskSCF::Media::V1::FrameSeq& translatedFrames);
 
 private:
+    boost::shared_mutex mMutex;
     AsteriskSCF::System::Logging::Logger mLogger;
     AsteriskSCF::Media::V1::StreamSinkSeq mSinks;
     AsteriskSCF::Media::V1::FormatSeq mSupportedFormats;
-    std::string mId;
+    const std::string mId;
 };
 
 typedef IceUtil::Handle<TranslatorSource> TranslatorSourcePtr;
diff --git a/test/TestMediaOperations.cpp b/test/TestMediaOperations.cpp
index eb28327..de58e83 100644
--- a/test/TestMediaOperations.cpp
+++ b/test/TestMediaOperations.cpp
@@ -1,7 +1,7 @@
 /*
  * Asterisk SCF -- An open-source communications framework.
  *
- * Copyright (C) 2011, Digium, Inc.
+ * Copyright (C) 2011-2012, Digium, Inc.
  *
  * See http://www.asterisk.org for more information about
  * the Asterisk SCF project. Please do not directly contact
@@ -460,8 +460,8 @@ BOOST_FIXTURE_TEST_CASE(createMediaOperations, PerTestFixture)
             ulawAlawFactory->createMediaOperation(AsteriskSCF::Operations::createContext(), 
                 Testbed.ulawSourceProxy, Testbed.alawSinkProxy);
 
-        BOOST_CHECK(alaw2ulawTranslator != 0);
-        BOOST_CHECK(ulaw2alawTranslator != 0);
+        BOOST_CHECK_NE(0, alaw2ulawTranslator);
+        BOOST_CHECK_NE(0, ulaw2alawTranslator);
 
         alaw2ulawTranslator->destroy();
         ulaw2alawTranslator->destroy();
@@ -474,6 +474,66 @@ BOOST_FIXTURE_TEST_CASE(createMediaOperations, PerTestFixture)
     }
 }
 
+BOOST_FIXTURE_TEST_CASE(testRetrySuccess, PerTestFixture)
+{
+    MediaOperationServiceLocatorParamsPtr ulawAlawParams = createLocatorParams(Testbed.alaw, Testbed.ulaw);
+
+    MediaOperationFactoryPrx ulawAlawFactory =
+        MediaOperationFactoryPrx::checkedCast(Testbed.locator->locate(ulawAlawParams));
+
+    BOOST_CHECK_NE(ulawAlawFactory, 0);
+
+    AsteriskSCF::System::V1::OperationContextPtr context = AsteriskSCF::Operations::createContext();
+
+    MediaOperationPrx expected =
+        ulawAlawFactory->createMediaOperation(context, Testbed.alawSourceProxy, Testbed.ulawSinkProxy);
+
+    MediaOperationPrx unexpected =
+        ulawAlawFactory->createMediaOperation(AsteriskSCF::Operations::createContext(),
+            Testbed.alawSourceProxy, Testbed.ulawSinkProxy);
+
+    // simulate a retry
+    MediaOperationPrx actual =
+        ulawAlawFactory->createMediaOperation(context, Testbed.alawSourceProxy, Testbed.ulawSinkProxy);
+
+    // This test is only meaningful if create operations return different proxies
+    BOOST_CHECK_NE(unexpected, actual);
+    BOOST_CHECK_EQUAL(expected, actual);
+}
+
+BOOST_FIXTURE_TEST_CASE(testRetryFailure, PerTestFixture)
+{
+    MediaOperationServiceLocatorParamsPtr ulawAlawParams = createLocatorParams(Testbed.alaw, Testbed.ulaw);
+
+    MediaOperationFactoryPrx ulawAlawFactory =
+        MediaOperationFactoryPrx::checkedCast(Testbed.locator->locate(ulawAlawParams));
+
+    BOOST_CHECK_NE(ulawAlawFactory, 0);
+
+    AsteriskSCF::System::V1::OperationContextPtr context = AsteriskSCF::Operations::createContext();
+
+    try
+    {
+        ulawAlawFactory->createMediaOperation(context, 0, 0);
+        BOOST_FAIL("Expected Ice::Exception on first invocation");
+    }
+    catch (const Ice::Exception&)
+    {
+        // expected
+    }
+
+    // simulate a retry
+    try
+    {
+        ulawAlawFactory->createMediaOperation(context, 0, 0);
+        BOOST_FAIL("Expected Ice::Exception on retry invocation");
+    }
+    catch (const Ice::Exception&)
+    {
+        // expected
+    }
+}
+
 BOOST_FIXTURE_TEST_CASE(translateAlawToUlaw, PerTestFixture)
 {
     size_t numFramesToTranslate = 10;

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


-- 
asterisk-scf/integration/media_operations_core.git



More information about the asterisk-scf-commits mailing list