[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