[asterisk-scf-commits] asterisk-scf/release/ice-util-cpp.git branch "master" updated.
Commits to the Asterisk SCF project code repositories
asterisk-scf-commits at lists.digium.com
Wed Aug 10 19:13:32 CDT 2011
branch "master" has been updated
via aa7afeacd622f141bb97c70c40a983243491433c (commit)
from 2efc4dd6dcc3a180f47a5c2b71c1809b2372c104 (commit)
Summary of changes:
include/AsteriskSCF/Collections/Set.h | 325 ++++++++++++++++++++
test/CMakeLists.txt | 1 +
test/Collections/CMakeLists.txt | 10 +
test/Collections/TestCollections.conf | 3 +
test/Collections/TestCollections.cpp | 324 +++++++++++++++++++
.../TestCollectionsIf.ice} | 27 ++-
6 files changed, 687 insertions(+), 3 deletions(-)
create mode 100644 include/AsteriskSCF/Collections/Set.h
create mode 100644 test/Collections/CMakeLists.txt
create mode 100644 test/Collections/TestCollections.conf
create mode 100644 test/Collections/TestCollections.cpp
copy test/{ProxyHelper/SimpleIf.ice => Collections/TestCollectionsIf.ice} (65%)
- Log -----------------------------------------------------------------
commit aa7afeacd622f141bb97c70c40a983243491433c
Author: Ken Hunt <ken.hunt at digium.com>
Date: Wed Aug 10 19:12:44 2011 -0500
Added Set.h and tests.
diff --git a/include/AsteriskSCF/Collections/Set.h b/include/AsteriskSCF/Collections/Set.h
new file mode 100644
index 0000000..ce250c3
--- /dev/null
+++ b/include/AsteriskSCF/Collections/Set.h
@@ -0,0 +1,325 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, 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.
+ */
+#pragma once
+
+#include <vector>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/thread/locks.hpp>
+
+#include <Ice/Ice.h>
+
+#include <AsteriskSCF/System/ExceptionsIf.h>
+#include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/Helpers/ProxyHelper.h>
+
+namespace AsteriskSCF
+{
+namespace Collections
+{
+
+/**
+ * Maintains a set of type T.
+ * The items are keyed on a type K.
+ * The set maintains at most one item of a given id.
+ * The id for an item is obtained via an overridable member function
+ * getIdentity().
+ */
+template <typename T, typename K, typename NullItemException>
+class Set
+{
+public:
+ Set(const Ice::ObjectAdapterPtr& adapter,
+ const AsteriskSCF::System::Logging::Logger& logger,
+ const std::string& loggingLabel,
+ bool doesThrow = true)
+ : mLogger(logger),
+ mLoggingLabel(loggingLabel),
+ mAdapter(adapter),
+ mDoesThrow(doesThrow)
+ {
+ }
+
+ Set(const Ice::ObjectAdapterPtr& adapter,
+ const std::string& loggingLabel,
+ bool doesThrow = true)
+ : mLogger(AsteriskSCF::System::Logging::getLoggerFactory().getLogger("AsteriskSCF.Collections")),
+ mLoggingLabel(loggingLabel),
+ mAdapter(adapter),
+ mDoesThrow(doesThrow)
+
+ {
+ }
+
+ int size()
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ return mMap.size();
+ }
+
+ /**
+ * Add a single item.
+ */
+ void add(const T& item)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ if (item == 0)
+ {
+ mLogger(AsteriskSCF::System::Logging::Warning) << "Attempting to add a null member for " << mLoggingLabel;
+ if (mDoesThrow)
+ {
+ throw NullItemException();
+ }
+ return;
+ }
+
+ K id = getIdentity(item);
+
+ if (mMap.find(id) != mMap.end())
+ {
+ mLogger(AsteriskSCF::System::Logging::Warning) << "Replacing member " << id << " for " << mLoggingLabel;
+ }
+
+ mMap[id] = item;
+ }
+
+ /**
+ * Add a vector of items.
+ */
+ void add(const std::vector<T>& items)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ for (std::vector<T>::const_iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i) == 0)
+ {
+ mLogger(AsteriskSCF::System::Logging::Warning) << "Attempting to add a null member for " << mLoggingLabel;
+ continue;
+ }
+
+ K id = getIdentity(*i);
+
+ if (mMap.find(id) != mMap.end())
+ {
+ mLogger(AsteriskSCF::System::Logging::Warning) << "Replacing member " << id << " for " << mLoggingLabel;
+ }
+
+ mMap[id] = (*i);
+ }
+ }
+
+ /**
+ * Remove a vector of items.
+ */
+ void remove(const std::vector<T>& items)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ std::vector<K> idsNotFound;
+
+ for (std::vector<T>::const_iterator i = items.begin(); i != items.end(); ++i)
+ {
+ K id = getIdentity(*i);
+
+ std::map<K, T>::iterator searchResult = mMap.find(id);
+ if (searchResult != mMap.end())
+ {
+ mMap.erase(searchResult);
+ }
+ else
+ {
+ idsNotFound.push_back(id);
+ }
+ }
+
+ for(std::vector<K>::const_iterator s = idsNotFound.begin(); s != idsNotFound.end(); ++s)
+ {
+ mLogger(AsteriskSCF::System::Logging::Warning) << "Attempted to remove non-existent member " << (*s);
+ }
+ }
+
+ /**
+ * Remove an item.
+ */
+ void remove(const T& item)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ K id = getIdentity(item);
+ std::map<K, T>::iterator searchResult = mMap.find(id);
+
+ if (searchResult != mMap.end())
+ {
+ mMap.erase(searchResult);
+ return;
+ }
+
+ mLogger(AsteriskSCF::System::Logging::Warning) << "Attempted to remove non-existent member " << id;
+ if (mDoesThrow)
+ {
+ throw AsteriskSCF::System::V1::UnknownObject(id);
+ }
+ }
+
+ /**
+ * Retrieves all the items in the set.
+ */
+ std::vector<T> getAll()
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ std::vector<T> result;
+
+ for (std::map<K,T>::const_iterator pair = mMap.begin(); pair != mMap.end(); ++pair)
+ {
+ result.push_back(pair->second);
+ }
+
+ return result;
+ }
+
+ /**
+ * Retrieves specific items from the set.
+ * The identies of the items in the collection passed in
+ * are used to retrieve from the managed set.
+ */
+ std::vector<T> get(const std::vector<T>& toRetrieve)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ std::vector<T> result;
+
+ for (std::vector<T>::const_iterator i = toRetrieve.begin(); i != toRetrieve.end(); ++i)
+ {
+ std::map<K,T>::const_iterator pair = mMap.find(getIdentity(*i));
+ if (pair != mMap.end())
+ {
+ result.push_back(pair->second);
+ }
+ }
+
+ return result;
+ }
+
+ T get(const K& key)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+ std::map<K, T>::const_iterator pair = mMap.find(key);
+
+ if (pair != mMap.end())
+ {
+ return pair->second;
+ }
+
+ if (mDoesThrow)
+ {
+ throw AsteriskSCF::System::V1::UnknownObject(key);
+ }
+ return 0;
+ }
+
+ bool has(K key)
+ {
+ boost::unique_lock<boost::shared_mutex> lock(mLock);
+
+ std::map<K, T>::const_iterator search = mMap.find(key);
+ return (search != mMap.end());
+ }
+
+ typedef boost::shared_ptr< Set<T, K, NullItemException> > SetPtr;
+
+protected:
+
+ virtual K getIdentity(const T& item) = 0;
+
+ AsteriskSCF::System::Logging::Logger mLogger;
+ std::string mLoggingLabel;
+ Ice::ObjectAdapterPtr mAdapter;
+ boost::shared_mutex mLock;
+ std::map<K, T> mMap;
+ bool mDoesThrow;
+};
+
+/**
+ * Maintains a set of handles of type S.
+ * The type S is assumed to be derived from Ice::Handle.
+ */
+ template <typename S>
+ class HandleSet : public Set<S, std::string, AsteriskSCF::System::V1::NullHandleException>
+ {
+ public:
+ HandleSet(const Ice::ObjectAdapterPtr& adapter,
+ const AsteriskSCF::System::Logging::Logger& logger,
+ const std::string& loggingLabel,
+ bool doesThrow = true)
+ : Set(adapter,
+ logger,
+ loggingLabel,
+ doesThrow)
+ {
+ }
+
+ HandleSet(const Ice::ObjectAdapterPtr& adapter,
+ const std::string& loggingLabel,
+ bool doesThrow = true)
+ : Set(adapter,
+ loggingLabel,
+ doesThrow)
+
+ {
+ }
+
+ protected:
+ virtual std::string getIdentity(const S& item)
+ {
+ return item->ice_id();
+ }
+ };
+
+/**
+* Maintains a set of proxies of type S.
+* The type S is assumed to be derived from Ice::Proxy.
+*/
+template <typename S>
+class ProxySet : public Set<S, std::string, AsteriskSCF::System::V1::NullProxyException>
+{
+public:
+ProxySet(const Ice::ObjectAdapterPtr& adapter,
+ const AsteriskSCF::System::Logging::Logger& logger,
+ const std::string& loggingLabel,
+ bool doesThrow = true)
+ : Set(adapter,
+ logger,
+ loggingLabel,
+ doesThrow)
+{
+}
+
+ProxySet(const Ice::ObjectAdapterPtr& adapter,
+ const std::string& loggingLabel,
+ bool doesThrow = true)
+ : Set(adapter,
+ loggingLabel,
+ doesThrow)
+
+{
+}
+
+protected:
+ virtual std::string getIdentity(const S& item)
+ {
+ return mAdapter->getCommunicator()->identityToString(item->ice_getIdentity());
+ }
+};
+
+} // end namespace Collections
+} // end namespace AsteriskSCF
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index e6e992c..068c0ed 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -16,6 +16,7 @@ astscf_test_icebox(astscf-ice-util-cpp-test config/IceUtilCppTests.conf)
add_subdirectory(Async)
add_subdirectory(Component)
+add_subdirectory(Collections)
add_subdirectory(Replication)
add_subdirectory(ThreadPool)
add_subdirectory(WorkQueue)
diff --git a/test/Collections/CMakeLists.txt b/test/Collections/CMakeLists.txt
new file mode 100644
index 0000000..87768a6
--- /dev/null
+++ b/test/Collections/CMakeLists.txt
@@ -0,0 +1,10 @@
+
+astscf_component_init(CollectionsTest)
+astscf_slice_collection(LOCAL PATH "${CMAKE_CURRENT_SOURCE_DIR}")
+astscf_component_add_files(CollectionsTest TestCollections.cpp)
+astscf_component_add_slices(CollectionsTest LOCAL TestCollectionsIf.ice)
+astscf_component_add_boost_libraries(CollectionsTest unit_test_framework thread date_time)
+astscf_component_add_slice_collection_libraries(CollectionsTest ASTSCF)
+astscf_component_build_icebox(CollectionsTest)
+astscf_test_icebox(CollectionsTest test/Collections/TestCollections.conf)
+target_link_libraries(CollectionsTest logging-client)
diff --git a/test/Collections/TestCollections.conf b/test/Collections/TestCollections.conf
new file mode 100644
index 0000000..fa50cb4
--- /dev/null
+++ b/test/Collections/TestCollections.conf
@@ -0,0 +1,3 @@
+
+IceBox.Service.CollectionsTest = CollectionsTest:create --log_level=all
+
diff --git a/test/Collections/TestCollections.cpp b/test/Collections/TestCollections.cpp
new file mode 100644
index 0000000..fb54ce9
--- /dev/null
+++ b/test/Collections/TestCollections.cpp
@@ -0,0 +1,324 @@
+/*
+ * 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 StateReplicatorComponentTestSuite
+#define BOOST_TEST_NO_MAIN
+
+#include <boost/test/unit_test.hpp>
+#include <boost/test/debug.hpp>
+
+#include <Ice/Ice.h>
+#include <AsteriskSCF/logger.h>
+#include <AsteriskSCF/Testing/IceBoxBoostTest.h>
+
+#include <TestCollectionsIf.h>
+#include <AsteriskSCF/Collections/Set.h>
+
+using namespace std;
+using namespace AsteriskSCF::Collections;
+using namespace AsteriskSCF::CollectionsTest;
+using namespace AsteriskSCF::System::Logging;
+using namespace AsteriskSCF::System::V1;
+
+namespace
+{
+Logger lg = getLoggerFactory().getLogger("AsteriskSCF.TestCollections");
+}
+
+class SampleListenerImpl : public SampleListener
+{
+public:
+ SampleListenerImpl() : mHiCalled(0) {}
+
+ void hiThere(const Ice::Current &)
+ {
+ mHiCalled++;
+ }
+
+int mHiCalled;
+};
+typedef IceUtil::Handle<SampleListenerImpl> SampleListenerImplPtr;
+
+struct GlobalData
+{
+public:
+ SampleListenerPrx prx1;
+ SampleListenerPrx prx2;
+ SampleListenerPrx prx3;
+
+ ChildValue1Ptr ptr1;
+ ChildValue2Ptr ptr2;
+ ChildValue3Ptr ptr3;
+};
+GlobalData global;
+
+/**
+ * A global fixture for Ice initialization.
+ * Provides setup/teardown for the entire set of tests.
+ */
+struct GlobalIceFixture
+{
+ GlobalIceFixture()
+ {
+ ::boost::debug::detect_memory_leaks(false);
+ ::boost::unit_test::unit_test_log.set_stream( std::cout );
+
+ int status = 0;
+ try
+ {
+ IceBoxTestEnv.adapter = IceBoxTestEnv.communicator->createObjectAdapterWithEndpoints("TestCollections","default");
+
+ SampleListenerImplPtr listener = new SampleListenerImpl();
+ global.prx1 = SampleListenerPrx::uncheckedCast(IceBoxTestEnv.adapter->addWithUUID(listener));
+
+ listener = new SampleListenerImpl();
+ global.prx2 = SampleListenerPrx::uncheckedCast(IceBoxTestEnv.adapter->addWithUUID(listener));
+
+ listener = new SampleListenerImpl();
+ global.prx3 = SampleListenerPrx::uncheckedCast(IceBoxTestEnv.adapter->addWithUUID(listener));
+
+ global.ptr1 = new ChildValue1();
+ global.ptr1->base = 1;
+ global.ptr1->foo = 500;
+
+ global.ptr2 = new ChildValue2();
+ global.ptr2->base = 2;
+ global.ptr2->bar = "bar";
+
+ global.ptr3 = new ChildValue3();
+ global.ptr3->base = 3;
+ }
+ catch (const Ice::Exception& ex)
+ {
+ cerr << ex << endl;
+ status = 1;
+ }
+ catch (const char* msg)
+ {
+ cerr << msg << endl;
+ status = 1;
+ }
+ } // end Fixture() constructor
+
+
+ ~GlobalIceFixture()
+ {
+ }
+};
+
+BOOST_GLOBAL_FIXTURE(GlobalIceFixture);
+
+
+struct PerTestFixture
+{
+public:
+ PerTestFixture()
+ {
+ }
+
+ ~PerTestFixture()
+ {
+ }
+
+};
+
+/**
+ * Test a proxy collection
+ */
+BOOST_AUTO_TEST_CASE(ProxySetTest)
+{
+ ProxySet<SampleListenerPrx> proxySet(IceBoxTestEnv.adapter, lg, "Sample Listeners");
+
+ /////////////////////////////////////////////////////////////
+ // Try accessing the empty set first.
+ // We'll try all the accessor operations just to make sure
+ // the template instantiation is fully compiled.
+
+ bool caught(false);
+ vector<SampleListenerPrx> results;
+
+ try
+ {
+ vector<SampleListenerPrx> toRetrieve;
+
+ toRetrieve.push_back(global.prx1);
+ toRetrieve.push_back(global.prx2);
+ results = proxySet.get(toRetrieve);
+ }
+ catch(const NullProxyException&)
+ {
+ caught = true;
+ }
+
+ BOOST_CHECK(caught == false);
+ BOOST_CHECK(results.size() == 0);
+
+ caught = false;
+ try
+ {
+ SampleListenerPrx single = proxySet.get("RandomNonsense");
+ }
+ catch(const UnknownObject&)
+ {
+ caught = true;
+ }
+
+ BOOST_CHECK(caught == true);
+
+ caught = false;
+ try
+ {
+ results = proxySet.getAll();
+ }
+ catch(...)
+ {
+ caught = true;
+ }
+
+ BOOST_CHECK(caught == false);
+ BOOST_CHECK(results.size() == 0);
+
+ BOOST_CHECK(proxySet.has("Something") == false);
+
+ ///////////////////////////////////////////////////////
+ // Now add some content added.
+
+ proxySet.add(global.prx1);
+
+ vector<SampleListenerPrx> multiple;
+ multiple.push_back(global.prx2);
+ multiple.push_back(global.prx3);
+
+ proxySet.add(multiple);
+
+ BOOST_CHECK(proxySet.has( IceBoxTestEnv.adapter->getCommunicator()->identityToString(global.prx1->ice_getIdentity())) == true);
+
+ BOOST_CHECK(proxySet.size() == 3);
+
+ proxySet.remove(global.prx2);
+
+ BOOST_CHECK(proxySet.size() == 2);
+
+ results = proxySet.getAll();
+ BOOST_CHECK(results.size() == 2);
+
+ SampleListenerPrx prx = proxySet.get(IceBoxTestEnv.adapter->getCommunicator()->identityToString(global.prx1->ice_getIdentity()));
+ BOOST_CHECK(prx->ice_getIdentity() == global.prx1->ice_getIdentity());
+
+ vector<SampleListenerPrx> toRetrieve;
+ toRetrieve.push_back(global.prx3);
+
+ results = proxySet.get(toRetrieve);
+ BOOST_CHECK(results.size() == 1);
+
+ vector<SampleListenerPrx> toRemove;
+ toRemove.push_back(global.prx1);
+ toRemove.push_back(global.prx3);
+
+ proxySet.remove(toRemove);
+
+ BOOST_CHECK(proxySet.size() == 0);
+}
+
+/**
+ * Test a handle collection
+ */
+BOOST_AUTO_TEST_CASE(HandleSetTest)
+{
+ HandleSet<BaseValuePtr> handleSet(IceBoxTestEnv.adapter, lg, "Values Set");
+
+ /////////////////////////////////////////////////////////////
+ // Try accessing the empty set first.
+ // We'll try all the accessor operations just to make sure
+ // the template instantiation is fully compiled.
+
+ bool caught(false);
+ vector<BaseValuePtr> results;
+
+ try
+ {
+ vector<BaseValuePtr> toRetrieve;
+
+ toRetrieve.push_back(global.ptr1);
+ toRetrieve.push_back(global.ptr2);
+ results = handleSet.get(toRetrieve);
+ }
+ catch(const NullProxyException&)
+ {
+ caught = true;
+ }
+
+ BOOST_CHECK(caught == false);
+ BOOST_CHECK(results.size() == 0);
+
+ caught = false;
+ try
+ {
+ BaseValuePtr single = handleSet.get("RandomNonsense");
+ }
+ catch(const UnknownObject&)
+ {
+ caught = true;
+ }
+
+ BOOST_CHECK(caught == true);
+
+ caught = false;
+ try
+ {
+ results = handleSet.getAll();
+ }
+ catch(...)
+ {
+ caught = true;
+ }
+
+ BOOST_CHECK(caught == false);
+ BOOST_CHECK(results.size() == 0);
+
+ BOOST_CHECK(handleSet.has("Something") == false);
+
+ ///////////////////////////////////////////////////////
+ // Now add some content added.
+
+ handleSet.add(global.ptr1);
+
+ vector<BaseValuePtr> multiple;
+ multiple.push_back(global.ptr2);
+ multiple.push_back(global.ptr3);
+
+ handleSet.add(multiple);
+
+ BOOST_CHECK(handleSet.has(global.ptr1->ice_id()) == true);
+
+ BOOST_CHECK(handleSet.size() == 3);
+
+ handleSet.remove(global.ptr2);
+
+ BOOST_CHECK(handleSet.size() == 2);
+
+ results = handleSet.getAll();
+ BOOST_CHECK(results.size() == 2);
+
+ BaseValuePtr ptr = handleSet.get(global.ptr1->ice_id());
+ BOOST_CHECK(ptr->ice_id() == global.ptr1->ice_id());
+
+ vector<BaseValuePtr> toRetrieve;
+ toRetrieve.push_back(global.ptr3);
+
+ results = handleSet.get(toRetrieve);
+ BOOST_CHECK(results.size() == 1);
+
+}
diff --git a/test/Collections/TestCollectionsIf.ice b/test/Collections/TestCollectionsIf.ice
new file mode 100644
index 0000000..c1ef54f
--- /dev/null
+++ b/test/Collections/TestCollectionsIf.ice
@@ -0,0 +1,48 @@
+/*
+ * Asterisk SCF -- An open-source communications framework.
+ *
+ * Copyright (C) 2010-2011, 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.
+ */
+#pragma once
+
+module AsteriskSCF
+{
+module CollectionsTest
+{
+interface SampleListener
+{
+ void hiThere();
+};
+
+class BaseValue
+{
+ int base;
+};
+
+class ChildValue1 extends BaseValue
+{
+ int foo;
+};
+
+class ChildValue2 extends BaseValue
+{
+ string bar;
+};
+
+class ChildValue3 extends BaseValue
+{
+ int other;
+};
+
+}; /* End of module CollectionsTest*/
+}; /* End of module AsteriskSCF */
\ No newline at end of file
-----------------------------------------------------------------------
--
asterisk-scf/release/ice-util-cpp.git
More information about the asterisk-scf-commits
mailing list