summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksandar Donchev <Aleksander.Donchev@partner.bmw.de>2017-03-06 17:10:32 +0100
committerChristian Linke <christian.linke@bmw.de>2017-05-02 06:25:51 -0700
commit99c3edf827a16d4bdc1c40a5df7c18bf8626afa3 (patch)
treebc0e5cdec2312cb69088dfa3810b19fb102a95f3
parent551d34d6f69e7def9590f503f23dad220011f118 (diff)
downloadaudiomanager-99c3edf827a16d4bdc1c40a5df7c18bf8626afa3.tar.gz
CAmSocketHandler - usage of std::function instead of function pointers,
code cleanup and minior optimizations. Signed-off-by: Christian Linke <christian.linke@bmw.de> Change-Id: I8c2c2c436ac9abc37c76a12245c731f327cab0e5
-rw-r--r--AudioManagerUtilities/include/CAmSocketHandler.h235
-rw-r--r--AudioManagerUtilities/src/CAmSocketHandler.cpp324
-rw-r--r--AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp375
-rw-r--r--AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h92
4 files changed, 640 insertions, 386 deletions
diff --git a/AudioManagerUtilities/include/CAmSocketHandler.h b/AudioManagerUtilities/include/CAmSocketHandler.h
index 7ccfd16..d7d4b38 100644
--- a/AudioManagerUtilities/include/CAmSocketHandler.h
+++ b/AudioManagerUtilities/include/CAmSocketHandler.h
@@ -26,9 +26,11 @@
#include <set>
#include <signal.h>
#include <vector>
+#include <functional>
#include <audiomanagerconfig.h>
#include "audiomanagertypes.h"
+
#ifdef WITH_TIMERFD
#include <stdio.h>
@@ -43,11 +45,11 @@ namespace am
{
#define MAX_NS 1000000000L
-#define MAX_TIMERHANDLE INT16_MAX
-#define MAX_POLLHANDLE INT16_MAX
+#define MAX_TIMERHANDLE UINT16_MAX
+#define MAX_POLLHANDLE UINT16_MAX
- typedef uint16_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
typedef uint16_t sh_pollHandle_t; //!<this is a handle for a filedescriptor to be used with the SocketHandler
+ typedef sh_pollHandle_t sh_timerHandle_t; //!<this is a handle for a timer to be used with the SocketHandler
/**
* prototype for poll prepared callback
@@ -214,21 +216,22 @@ namespace am
/**
* template for a callback
*/
+
template<class TClass> class TAmShPollPrepare: public IAmShPollPrepare
{
private:
TClass* mInstance;
- void (TClass::*mFunction)(const sh_timerHandle_t handle, void* userData);
+ void (TClass::*mFunction)(const sh_pollHandle_t handle, void* userData);
public:
- TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_timerHandle_t handle, void* userData)) :
+ TAmShPollPrepare(TClass* instance, void (TClass::*function)(const sh_pollHandle_t handle, void* userData)) :
mInstance(instance), //
mFunction(function)
{
}
;
- virtual void Call(const sh_timerHandle_t handle, void* userData)
+ virtual void Call(const sh_pollHandle_t handle, void* userData)
{
(*mInstance.*mFunction)(handle, userData);
}
@@ -245,12 +248,17 @@ namespace am
struct sh_poll_s //!<struct that holds information about polls
{
sh_pollHandle_t handle; //!<handle to uniquely adress a filedesriptor
- IAmShPollPrepare *prepareCB; //!<pointer to preperation callback
- IAmShPollFired *firedCB; //!<pointer to fired callback
- IAmShPollCheck *checkCB; //!< pointer to check callback
- IAmShPollDispatch *dispatchCB; //!<pointer to dispatch callback
pollfd pollfdValue; //!<the array for polling the filedescriptors
- void *userData; //!<userdata saved together with the callback.
+ std::function<void(const sh_pollHandle_t handle, void* userData)> prepareCB; //preperation callback
+ std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> firedCB; //fired callback
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> checkCB; //check callback
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatchCB; //dispatch callback
+ void* userData;
+
+ sh_poll_s() :
+ handle(0), pollfdValue(), prepareCB(), firedCB(), checkCB(), dispatchCB(), userData(0)
+ {
+ }
};
struct sh_timer_s //!<struct that holds information of timers
@@ -262,56 +270,42 @@ namespace am
#else
timespec countdown; //!<the countdown, this value is decreased every time the timer is up
#endif
- IAmShTimerCallBack* callback; //!<the callbackfunction
- void * userData; //!<saves a void pointer together with the rest.
+ std::function<void(const sh_timerHandle_t handle, void* userData)> callback; //timer callback
+ void* userData;
+ sh_timer_s() :
+ handle(0)
+#ifdef WITH_TIMERFD
+ , fd(0)
+#endif
+ , countdown(), callback(), userData(0)
+ {
+ }
};
typedef std::reverse_iterator<sh_timer_s> rListTimerIter; //!<typedef for reverseiterator on timer lists
- typedef std::vector<pollfd> mListPollfd_t; //!<vector of filedescriptors
- typedef std::vector<sh_poll_s> mListPoll_t; //!<list for the callbacks
+ typedef std::vector<pollfd> VectorListPollfd_t; //!<vector of filedescriptors
+ typedef std::vector<sh_poll_s> VectorListPoll_t; //!<list for the callbacks
-#ifdef WITH_TIMERFD
- /**
- * Wrapper for IAmShTimerCallBack.
- * Timerfds are normal file descriptors and therefore they should be added to the handler through the method addFDPoll.
- */
- class TAmShPollTimerFired: public IAmShPollFired, public IAmShPollCheck
- {
- IAmShTimerCallBack* mCallback;
- uint64_t mExpirations;
- public:
- TAmShPollTimerFired(IAmShTimerCallBack * cb) :
- mCallback(cb), mExpirations(0)
- {
- }
-
- void Call(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
- {
- if (read(pollfd.fd, &mExpirations, sizeof(uint64_t)) == -1)
- {
- //error received...try again
- read(pollfd.fd, &mExpirations, sizeof(uint64_t));
- }
- }
-
- bool Call(const sh_pollHandle_t handle, void* userData)
- {
- mCallback->Call(handle, userData);
- return false;
- }
- };
-#endif
public:
CAmSocketHandler();
~CAmSocketHandler();
- am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check,
- IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle);
+ am_Error_e addFDPoll(const int fd, const short event, std::function<void(const sh_pollHandle_t handle, void* userData)> prepare, std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> fired,
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> check, std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatch, void* userData, sh_pollHandle_t& handle);
+
+ am_Error_e addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void* userData, sh_pollHandle_t& handle);
am_Error_e removeFDPoll(const sh_pollHandle_t handle);
am_Error_e updateEventFlags(const sh_pollHandle_t handle, const short events);
- am_Error_e addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void* userData,
+ am_Error_e addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData,
+#ifndef WITH_TIMERFD
+ const bool __attribute__((__unused__)) repeats = false
+#else
+ const bool repeats = false
+#endif
+ );
+ am_Error_e addTimer(const timespec & timeouts, std::function<void(const sh_timerHandle_t handle, void* userData)> callback, sh_timerHandle_t& handle, void* userData,
#ifndef WITH_TIMERFD
const bool __attribute__((__unused__)) repeats = false
#else
@@ -325,26 +319,8 @@ namespace am
void start_listenting();
void stop_listening();
void exit_mainloop();
- void receiverCallback(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)
- {
- (void) pollfd;
- (void) handle;
- (void) userData;
- }
-
- bool checkerCallback(const sh_pollHandle_t handle, void* userData)
- {
- (void) handle;
- (void) userData;
- return (false);
- }
private:
- TAmShPollFired<CAmSocketHandler> mReceiverCallbackT;
- TAmShPollCheck<CAmSocketHandler> mCheckerCallbackT;
-#ifdef WITH_TIMERFD
- std::list<TAmShPollTimerFired> mTimerCallbackT;
-#endif
static CAmSocketHandler* mInstance;
int mPipe[2];
@@ -444,121 +420,54 @@ namespace am
return (0);
}
#endif
+
+ /**
+ * functor to prepare all fire events
+ * @param a
+ * @return
+ */
+ inline static void prepare(am::CAmSocketHandler::sh_poll_s& row);
+
/**
* functor to return all fired events
* @param a
* @return
*/
- inline static bool eventFired(const pollfd& a)
- {
- return (a.revents == 0 ? false : true);
- }
+ inline static void fire(sh_poll_s* a);
+
+
+ /**
+ * functor to return all fired events
+ * @param a
+ * @return
+ */
+ inline static bool eventFired(const pollfd& a);
+
/**
* functor to help find the items that do not need dispatching
* @param a
* @return
*/
- inline static bool noDispatching(const sh_poll_s& a)
- {
- //remove from list of there is no checkCB
- if (!a.checkCB)
- return (true);
- return (!a.checkCB->Call(a.handle, a.userData));
- }
+ inline static bool noDispatching(const sh_poll_s* a);
/**
* checks if dispatching is already finished
* @param a
* @return
*/
- inline static bool dispatchingFinished(const sh_poll_s& a)
- {
- //remove from list of there is no dispatchCB
- if (!a.dispatchCB)
- return (true);
- return (!a.dispatchCB->Call(a.handle, a.userData));
- }
-
- class CAmShCopyPollfd //!< functor to copy filedescriptors into the poll array
- {
- private:
- mListPollfd_t& mArray;
- public:
- CAmShCopyPollfd(mListPollfd_t& dest) :
- mArray(dest)
- {
- }
- void operator()(const sh_poll_s& row);
- };
-
- class CAmShCallFire //!< functor to call the firecallbacks
- {
- public:
- CAmShCallFire()
- {
- }
- ;
- void operator()(sh_poll_s& row);
- };
-
- class CAmShCallPrep //!< functor to call the preparation callbacks
- {
- public:
- CAmShCallPrep()
- {
- }
- ;
- void operator()(sh_poll_s& row);
- };
+ inline static bool dispatchingFinished(const sh_poll_s* a);
- class CAmShCallTimer //!<functor to call a timer
- {
- public:
- CAmShCallTimer()
- {
- }
- ;
- void operator()(sh_timer_s& row);
- };
-
- class CAmShCountdownUp //!<functor that checks if a timer is up
- {
- private:
- timespec mDiffTime;
- public:
- CAmShCountdownUp(const timespec& differenceTime) :
- mDiffTime(differenceTime)
- {
- }
- ;
- bool operator()(const sh_timer_s& row);
- };
-#ifndef WITH_TIMERFD
- class CAmShCountdownZero //!<functor that checks if a timer is zero
- {
- public:
- CAmShCountdownZero()
- {};
- bool operator()(const sh_timer_s& row);
- };
-
- class CAmShSubstractTime //!<functor to easy substract from each countdown value
- {
- private:
- timespec param;
- public:
- CAmShSubstractTime(timespec param) : param(param)
- {}
- inline void operator()(sh_timer_s& t)
- {
- t.countdown = timespecSub(t.countdown, param);
- }
- };
-#endif
- mListPollfd_t mfdPollingArray; //!<the polling array for ppoll
+ /**
+ * timer fire callback
+ * @param a
+ * @return
+ */
+ inline static void callTimer(sh_timer_s& a);
+
+ VectorListPollfd_t mfdPollingArray; //!<the polling array for ppoll
std::set<sh_pollHandle_t> mSetPollKeys; //!A set of all used ppoll keys
- mListPoll_t mListPoll; //!<list that holds all information for the ppoll
+ VectorListPoll_t mListPoll; //!<list that holds all information for the ppoll
std::set<sh_timerHandle_t> mSetTimerKeys; //!A set of all used timer keys
std::list<sh_timer_s> mListTimer; //!<list of all timers
std::list<sh_timer_s> mListActiveTimer; //!<list of all currently active timers
diff --git a/AudioManagerUtilities/src/CAmSocketHandler.cpp b/AudioManagerUtilities/src/CAmSocketHandler.cpp
index 56df45c..9ee7996 100644
--- a/AudioManagerUtilities/src/CAmSocketHandler.cpp
+++ b/AudioManagerUtilities/src/CAmSocketHandler.cpp
@@ -42,12 +42,7 @@ namespace am
{
CAmSocketHandler::CAmSocketHandler() :
- mReceiverCallbackT(this, &CAmSocketHandler::receiverCallback), //
- mCheckerCallbackT(this, &CAmSocketHandler::checkerCallback), //
-#ifdef WITH_TIMERFD
- mTimerCallbackT(), //
-#endif
- mPipe(), //
+ mPipe(), //
mDispatchDone(1), //
mListPoll(), //
mListTimer(), //
@@ -56,7 +51,7 @@ namespace am
mLastInsertedPollHandle(0), //
mRecreatePollfds(true)
#ifndef WITH_TIMERFD
- ,mStartTime() //
+ ,mStartTime() //
#endif
{
if (pipe(mPipe) == -1)
@@ -68,13 +63,13 @@ namespace am
short event = 0;
sh_pollHandle_t handle;
event |= POLLIN;
- addFDPoll(mPipe[0], event, NULL, &mReceiverCallbackT, &mCheckerCallbackT, NULL, NULL, handle);
+ addFDPoll(mPipe[0], event, NULL, [](const pollfd pollfd, const sh_pollHandle_t, void*){}, [](const sh_pollHandle_t, void*){ return (false);}, NULL, NULL, handle);
}
CAmSocketHandler::~CAmSocketHandler()
{
#ifdef WITH_TIMERFD
- for(auto it: mListTimer)
+ for (auto it : mListTimer)
{
close(it.fd);
}
@@ -103,24 +98,38 @@ namespace am
#ifndef WITH_TIMERFD
clock_gettime(CLOCK_MONOTONIC, &mStartTime);
#endif
- while (!mDispatchDone)
+ timespec buffertime;
+ //freeze mListPoll by copying it - otherwise we get problems when we want to manipulate it during the next lines
+ std::list<sh_poll_s*> listPoll;
+ VectorListPoll_t::iterator listmPollIt;
+
+ auto preparePollfd = [&](const sh_poll_s& row)
{
- //first we go through the registered filedescriptors and check if someone needs preparation:
- std::for_each(mListPoll.begin(), mListPoll.end(), CAmShCallPrep());
+ CAmSocketHandler::prepare((sh_poll_s&)row);
+ pollfd temp = row.pollfdValue;
+ temp.revents = 0;
+ mfdPollingArray.push_back(temp);
+ };
+ while (!mDispatchDone)
+ {
if (mRecreatePollfds)
{
mfdPollingArray.clear();
//there was a change in the setup, so we need to recreate the fdarray from the list
- std::for_each(mListPoll.begin(), mListPoll.end(), CAmShCopyPollfd(mfdPollingArray));
+ std::for_each(mListPoll.begin(), mListPoll.end(), preparePollfd);
mRecreatePollfds = false;
}
+ else
+ {
+ //first we go through the registered filedescriptors and check if someone needs preparation:
+ std::for_each(mListPoll.begin(), mListPoll.end(), CAmSocketHandler::prepare);
+ }
#ifndef WITH_TIMERFD
timerCorrection();
#endif
//block until something is on a filedescriptor
- timespec buffertime;
if ((pollStatus = ppoll(&mfdPollingArray[0], mfdPollingArray.size(), insertTime(buffertime), &sigmask)) < 0)
{
if (errno == EINTR)
@@ -138,36 +147,26 @@ namespace am
if (pollStatus != 0) //only check filedescriptors if there was a change
{
//todo: here could be a timer that makes sure naughty plugins return!
-
- //freeze mListPoll by copying it - otherwise we get problems when we want to manipulate it during the next lines
- std::list<sh_poll_s> listPoll;
- mListPoll_t::iterator listmPollIt;
-
- //remove all filedescriptors who did not fire
- std::vector<pollfd>::iterator it = mfdPollingArray.begin();
- do
+ listPoll.clear();
+ //stage 0+1, call firedCB
+ for (VectorListPollfd_t::iterator itMfdPollingArray = mfdPollingArray.begin(); itMfdPollingArray != mfdPollingArray.end(); itMfdPollingArray++)
{
- it = std::find_if(it, mfdPollingArray.end(), eventFired);
- if (it != mfdPollingArray.end())
+ if (CAmSocketHandler::eventFired(*itMfdPollingArray))
{
- listmPollIt = mListPoll.begin();
- std::advance(listmPollIt, std::distance(mfdPollingArray.begin(), it));
- listPoll.push_back(*listmPollIt);
- listPoll.back().pollfdValue = *it;
- it++;
+ listmPollIt = mListPoll.begin() + (itMfdPollingArray - mfdPollingArray.begin());
+ am::CAmSocketHandler::sh_poll_s * pollItem = &((am::CAmSocketHandler::sh_poll_s&) (*listmPollIt));
+ listPoll.push_back(pollItem);
+ CAmSocketHandler::fire(pollItem);
}
- } while (it != mfdPollingArray.end());
-
- //stage 1, call firedCB
- std::for_each(listPoll.begin(), listPoll.end(), CAmShCallFire());
+ }
//stage 2, lets ask around if some dispatching is necessary, the ones who need stay on the list
- listPoll.erase(std::remove_if(listPoll.begin(), listPoll.end(), noDispatching), listPoll.end());
+ listPoll.erase(std::remove_if(listPoll.begin(), listPoll.end(), CAmSocketHandler::noDispatching), listPoll.end());
//stage 3, the ones left need to dispatch, we do this as long as there is something to dispatch..
do
{
- listPoll.erase(std::remove_if(listPoll.begin(), listPoll.end(), dispatchingFinished), listPoll.end());
+ listPoll.erase(std::remove_if(listPoll.begin(), listPoll.end(), CAmSocketHandler::dispatchingFinished), listPoll.end());
} while (!listPoll.empty());
}
@@ -175,6 +174,7 @@ namespace am
else //Timerevent
{
//this was a timer event, we need to take care about the timers
+ //find out the timedifference to starttime
timerUp();
}
#endif
@@ -194,7 +194,8 @@ namespace am
timespec currentTime, correctionTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
correctionTime = timespecSub(currentTime, mStartTime);
- std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(correctionTime));
+ std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), [&correctionTime](sh_timer_s& t)
+ { t.countdown = timespecSub(t.countdown, correctionTime);});
}
#endif
}
@@ -213,16 +214,18 @@ namespace am
* Adds a filedescriptor to the polling loop
* @param fd the filedescriptor
* @param event the event flags
- * @param prepare a callback that is called before the loop is entered
- * @param fired a callback that is called when the filedescriptor needs to be read
- * @param check a callback that is called to check if further actions are neccessary
- * @param dispatch a callback that is called to dispatch the received data
+ * @param prepare a std::function that is called before the loop is entered
+ * @param fired a std::function that is called when the filedescriptor needs to be read
+ * @param check a std::function that is called to check if further actions are neccessary
+ * @param dispatch a std::function that is called to dispatch the received data
* @param userData a pointer to userdata that is always passed around
* @param handle the handle of this poll
* @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid
*/
- am::am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check,
- IAmShPollDispatch *dispatch, void *userData, sh_pollHandle_t & handle)
+
+ am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, std::function<void(const sh_pollHandle_t handle, void* userData)> prepare,
+ std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> fired, std::function<bool(const sh_pollHandle_t handle, void* userData)> check,
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatch, void* userData, sh_pollHandle_t& handle)
{
if (!fdIsValid(fd))
return (E_NON_EXISTENT);
@@ -251,12 +254,11 @@ namespace am
pollData.handle = mLastInsertedPollHandle;
pollData.pollfdValue.events = event;
pollData.pollfdValue.revents = 0;
- pollData.userData = userData;
pollData.prepareCB = prepare;
pollData.firedCB = fired;
pollData.checkCB = check;
pollData.dispatchCB = dispatch;
-
+ pollData.userData = userData;
//add new data to the list
mListPoll.push_back(pollData);
@@ -267,13 +269,45 @@ namespace am
}
/**
+ * Adds a filedescriptor to the polling loop
+ * @param fd the filedescriptor
+ * @param event the event flags
+ * @param prepare a callback that is called before the loop is entered
+ * @param fired a callback that is called when the filedescriptor needs to be read
+ * @param check a callback that is called to check if further actions are neccessary
+ * @param dispatch a callback that is called to dispatch the received data
+ * @param userData a pointer to userdata that is always passed around
+ * @param handle the handle of this poll
+ * @return E_OK if the descriptor was added, E_NON_EXISTENT if the fd is not valid
+ */
+ am::am_Error_e CAmSocketHandler::addFDPoll(const int fd, const short event, IAmShPollPrepare *prepare, IAmShPollFired *fired, IAmShPollCheck *check, IAmShPollDispatch *dispatch, void *userData, sh_pollHandle_t & handle)
+ {
+
+ std::function<void(const sh_pollHandle_t handle, void* userData)> prepareCB; //preperation callback
+ std::function<void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)> firedCB; //fired callback
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> checkCB; //check callback
+ std::function<bool(const sh_pollHandle_t handle, void* userData)> dispatchCB; //check callback
+
+ if (prepare)
+ prepareCB = std::bind(&IAmShPollPrepare::Call, prepare, std::placeholders::_1, std::placeholders::_2);
+ if (fired)
+ firedCB = std::bind(&IAmShPollFired::Call, fired, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
+ if (check)
+ checkCB = std::bind(&IAmShPollCheck::Call, check, std::placeholders::_1, std::placeholders::_2);
+ if (dispatch)
+ dispatchCB = std::bind(&IAmShPollDispatch::Call, dispatch, std::placeholders::_1, std::placeholders::_2);
+
+ return addFDPoll(fd, event, prepareCB, firedCB, checkCB, dispatchCB, userData, handle);
+ }
+
+ /**
* removes a filedescriptor from the poll loop
* @param handle
* @return
*/
am_Error_e CAmSocketHandler::removeFDPoll(const sh_pollHandle_t handle)
{
- mListPoll_t::iterator iterator = mListPoll.begin();
+ VectorListPoll_t::iterator iterator = mListPoll.begin();
for (; iterator != mListPoll.end(); ++iterator)
{
@@ -299,11 +333,21 @@ namespace am
* @param userData pointer always passed with the call
* @return E_OK in case of success
*/
- am_Error_e CAmSocketHandler::addTimer(const timespec timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, const bool repeats)
+
+ am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, IAmShTimerCallBack* callback, sh_timerHandle_t& handle, void * userData, const bool repeats)
{
- assert(!((timeouts.tv_sec == 0) && (timeouts.tv_nsec == 0)));
assert(callback!=NULL);
+ std::function<void(const sh_timerHandle_t handle, void* userData)> callbackFunc;
+ callbackFunc = std::bind(&IAmShTimerCallBack::Call, callback, std::placeholders::_1, std::placeholders::_2);
+
+ return addTimer(timeouts, callbackFunc, handle, userData, repeats);
+ }
+
+ am_Error_e CAmSocketHandler::addTimer(const timespec & timeouts, std::function<void(const sh_timerHandle_t handle, void* userData)> callback, sh_timerHandle_t& handle, void * userData, const bool repeats)
+ {
+ assert(!((timeouts.tv_sec == 0) && (timeouts.tv_nsec == 0)));
+
mListTimer.emplace_back();
sh_timer_s & timerItem = mListTimer.back();
@@ -339,7 +383,7 @@ namespace am
timespec currentTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
if (!mDispatchDone)//the mainloop is started
- timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
+ timerItem.countdown = timespecAdd(timeouts, timespecSub(currentTime, mStartTime));
mListTimer.push_back(timerItem);
mListActiveTimer.push_back(timerItem);
mListActiveTimer.sort(compareCountdown);
@@ -347,7 +391,7 @@ namespace am
#else
timerItem.countdown.it_value = timeouts;
- if(repeats)
+ if (repeats)
timerItem.countdown.it_interval = timeouts;
else
{
@@ -357,25 +401,35 @@ namespace am
timerItem.countdown.it_interval = zero;
}
- timerItem.callback = callback;
- timerItem.userData = userData;
timerItem.fd = -1;
+ timerItem.userData = userData;
am_Error_e err = createTimeFD(timerItem.countdown, timerItem.fd);
if (err != E_OK)
{
mListTimer.pop_back();
return err;
}
- mTimerCallbackT.emplace_back(callback);
-
- err = addFDPoll(timerItem.fd, POLLIN, NULL, &mTimerCallbackT.back(), &mTimerCallbackT.back(), NULL, NULL, handle);
+
+ static auto actionPoll = [](const pollfd pollfd, const sh_pollHandle_t handle, void* userData){
+ uint64_t mExpirations;
+ if (read(pollfd.fd, &mExpirations, sizeof(uint64_t)) == -1)
+ {
+ //error received...try again
+ read(pollfd.fd, &mExpirations, sizeof(uint64_t));
+ }
+ };
+
+ err = addFDPoll(timerItem.fd, POLLIN, NULL, actionPoll, [callback](const sh_pollHandle_t handle, void* userData)->bool{
+ callback(handle, userData);
+ return false;
+ },
+ NULL, userData, handle);
if (E_OK == err)
{
timerItem.handle = handle;
}
else
{
- mTimerCallbackT.pop_back();
mListTimer.pop_back();
}
return err;
@@ -611,6 +665,7 @@ namespace am
logError("Failed to set timer duration");
return E_NOT_POSSIBLE;
}
+ return (E_OK);
#else
//go through the list and remove the timer with the handle
std::list<sh_timer_s>::iterator it(mListActiveTimer.begin());
@@ -634,7 +689,7 @@ namespace am
*/
am_Error_e CAmSocketHandler::updateEventFlags(const sh_pollHandle_t handle, const short events)
{
- mListPoll_t::iterator iterator = mListPoll.begin();
+ VectorListPoll_t::iterator iterator = mListPoll.begin();
for (; iterator != mListPoll.end(); ++iterator)
{
@@ -665,12 +720,20 @@ namespace am
void CAmSocketHandler::timerUp()
{
//find out the timedifference to starttime
- timespec currentTime, diffTime;
+ static timespec currentTime, diffTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
diffTime = timespecSub(currentTime, mStartTime);
+ static auto countdownUp = [&](const sh_timer_s& row)->bool
+ {
+ timespec sub = timespecSub(row.countdown, diffTime);
+ if (sub.tv_nsec == 0 && sub.tv_sec == 0)
+ return (true);
+ return (false);
+ };
+
//now we need to substract the diffTime from all timers and see if they are up
- std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownUp(diffTime));
+ std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownUp);
//copy all fired timers into a list
std::vector<sh_timer_s> tempList(overflowIter, mListActiveTimer.rend());
@@ -680,7 +743,7 @@ namespace am
mListActiveTimer.erase(mListActiveTimer.begin(), it);
//call the callbacks for the timers
- std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
+ std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer);
}
/**
@@ -689,19 +752,31 @@ namespace am
void CAmSocketHandler::timerCorrection()
{
//get the current time and calculate the correction value
- timespec currentTime, correctionTime;
+ static timespec currentTime, correctionTime;
clock_gettime(CLOCK_MONOTONIC, &currentTime);
correctionTime = timespecSub(currentTime, mStartTime);
mStartTime = currentTime;
+ static auto countdownZero = [](const sh_timer_s& row)->bool
+ {
+ if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
+ return (true);
+ return (false);
+ };
+
+ static auto substractTime = [&](sh_timer_s& t)
+ {
+ t.countdown = timespecSub(t.countdown, correctionTime);
+ };
+
if (!mListActiveTimer.empty())
{
//subtract the correction value from all items in the list
- std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), CAmShSubstractTime(correctionTime));
+ std::for_each(mListActiveTimer.begin(), mListActiveTimer.end(), substractTime);
//find the last occurrence of zero -> timer overflowed
- std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownZero());
+ std::list<sh_timer_s>::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownZero);
//only if a timer overflowed
if (overflowIter != mListActiveTimer.rend())
@@ -714,11 +789,74 @@ namespace am
mListActiveTimer.erase(mListActiveTimer.begin(), it);
//call the callbacks for the timers
- std::for_each(tempList.begin(), tempList.end(), CAmShCallTimer());
+ std::for_each(tempList.begin(), tempList.end(), CAmSocketHandler::callTimer);
}
}
}
#endif
+
+ /**
+ * prepare for poll
+ */
+ void CAmSocketHandler::prepare(am::CAmSocketHandler::sh_poll_s& row)
+ {
+ if (row.prepareCB)
+ {
+ try
+ {
+ row.prepareCB(row.handle, row.userData);
+ } catch (std::exception& e)
+ {
+ logError("Sockethandler: Exception in Preparecallback,caught", e.what());
+ }
+ }
+ }
+
+
+ /**
+ * fire callback
+ */
+ void CAmSocketHandler::fire(sh_poll_s* a)
+ {
+ try
+ {
+ a->firedCB(a->pollfdValue, a->handle, a->userData);
+ } catch (std::exception& e)
+ {
+ logError("Sockethandler: Exception in FireCallback,caught", e.what());
+ }
+ }
+
+ /**
+ * event triggered
+ */
+ bool CAmSocketHandler::eventFired(const pollfd& a)
+ {
+ return (a.revents == 0 ? false : true);
+ }
+
+ /**
+ * should disptach
+ */
+ bool CAmSocketHandler::noDispatching(const sh_poll_s* a)
+ {
+ //remove from list of there is no checkCB
+ if (!a->checkCB)
+ return (true);
+ return (!a->checkCB(a->handle, a->userData));
+ }
+
+ /**
+ * disptach
+ */
+ bool CAmSocketHandler::dispatchingFinished(const sh_poll_s* a)
+ {
+ //remove from list of there is no dispatchCB
+ if (!a->dispatchCB)
+ return (true);
+ return (!a->dispatchCB(a->handle, a->userData));
+ }
+
/**
* is used to set the pointer for the ppoll command
* @param buffertime
@@ -742,17 +880,12 @@ namespace am
#ifdef WITH_TIMERFD
am_Error_e CAmSocketHandler::createTimeFD(const itimerspec & timeouts, int & fd)
{
- fd = timerfd_create(CLOCK_MONOTONIC, 0);
+ fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
if (fd <= 0)
{
logError("Failed to create timer");
return E_NOT_POSSIBLE;
}
- if (fcntl(fd, F_SETFL, O_NONBLOCK))
- {
- logError("Failed to set to non blocking mode");
- return E_NOT_POSSIBLE;
- }
if (timerfd_settime(fd, 0, &timeouts, NULL))
{
@@ -763,65 +896,16 @@ namespace am
}
#endif
- void CAmSocketHandler::CAmShCallFire::operator()(sh_poll_s& row)
- {
- try
- {
- row.firedCB->Call(row.pollfdValue, row.handle, row.userData);
- } catch (std::exception& e)
- {
- logError("Sockethandler: Exception in FireCallback,caught", e.what());
- }
- }
-
- void CAmSocketHandler::CAmShCallPrep::operator()(sh_poll_s& row)
- {
- if (row.prepareCB)
- {
- try
- {
- row.prepareCB->Call(row.handle, row.userData);
- } catch (std::exception& e)
- {
- logError("Sockethandler: Exception in Preparecallback,caught", e.what());
- }
- }
- }
-
- void CAmSocketHandler::CAmShCallTimer::operator()(sh_timer_s& row)
+ void CAmSocketHandler::callTimer(sh_timer_s& a)
{
try
{
- row.callback->Call(row.handle, row.userData);
+ a.callback(a.handle, a.userData);
} catch (std::exception& e)
{
logError("Sockethandler: Exception in Timercallback,caught", e.what());
}
}
- void CAmSocketHandler::CAmShCopyPollfd::operator()(const sh_poll_s& row)
- {
- pollfd temp = row.pollfdValue;
- temp.revents = 0;
- mArray.push_back(temp);
- }
-
-#ifndef WITH_TIMERFD
-bool CAmSocketHandler::CAmShCountdownUp::operator()(const sh_timer_s& row)
-{
- timespec sub = timespecSub(row.countdown, mDiffTime);
- if (sub.tv_nsec == 0 && sub.tv_sec == 0)
- return (true);
- return (false);
-}
-
-bool CAmSocketHandler::CAmShCountdownZero::operator()(const sh_timer_s& row)
-{
- if (row.countdown.tv_nsec == 0 && row.countdown.tv_sec == 0)
- return (true);
- return (false);
-}
-#endif
-
}
diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp
index 50e2aa9..6f4f184 100644
--- a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp
+++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.cpp
@@ -30,6 +30,7 @@
#include <fcntl.h>
#include <sys/un.h>
#include <sys/poll.h>
+
#include "CAmSocketHandler.h"
//todo: expand test, implement more usecases
@@ -37,9 +38,16 @@
#define SOCK_PATH "/tmp/mysock"
+#define SOCKET_TEST_LOOPS_COUNT 1000
+
using namespace testing;
using namespace am;
+static const char * TEST_SOCKET_DATA = "Got It?";
+static const char * TEST_SOCKET_DATA_FINAL = "finish!";
+
+static const std::chrono::time_point<std::chrono::high_resolution_clock> TP_ZERO;
+
CAmSocketHandlerTest::CAmSocketHandlerTest()
{
}
@@ -48,97 +56,254 @@ CAmSocketHandlerTest::~CAmSocketHandlerTest()
{
}
-CAmTimerCb::CAmTimerCb(CAmSocketHandler *myHandler) :
- pTimer1Callback(this, &CAmTimerCb::timer1Callback), //
- pTimer2Callback(this, &CAmTimerCb::timer2Callback), //
- pTimer3Callback(this, &CAmTimerCb::timer3Callback), //
- pTimer4Callback(this, &CAmTimerCb::timer4Callback), //
- mSocketHandler(myHandler)
+void CAmSocketHandlerTest::SetUp()
+{
+
+}
+void CAmSocketHandlerTest::TearDown()
{
}
-am::CAmTimerCb::~CAmTimerCb()
+CAmTimerSockethandlerController::CAmTimerSockethandlerController(CAmSocketHandler *myHandler, const timespec &timeout) :
+ MockIAmTimerCb(), mpSocketHandler(myHandler), mUpdateTimeout(timeout), pTimerCallback(this, &CAmTimerSockethandlerController::timerCallback)
{
}
-void am::CAmTimerCb::timer1Callback(sh_timerHandle_t handle, void* userData)
+am::CAmTimerSockethandlerController::~CAmTimerSockethandlerController()
{
- (void) handle;
- (void) userData;
- std::cout << "callback1 called" << std::endl;
- timespec timeout;
- timeout.tv_nsec = 0;
- timeout.tv_sec = 1;
- mSocketHandler->updateTimer(handle,timeout);
}
-void am::CAmTimerCb::timer2Callback(sh_timerHandle_t handle, void* userData)
+void am::CAmTimerSockethandlerController::timerCallback(sh_timerHandle_t handle, void* userData)
{
- (void) handle;
- (void) userData;
- std::cout << "callback2 called" << std::endl;
- timespec timeout;
- timeout.tv_nsec = 011110000;
- timeout.tv_sec = 1;
- mSocketHandler->updateTimer(handle,timeout);
+ MockIAmTimerCb::timerCallback(handle, userData);
+ mpSocketHandler->stop_listening();
}
-void am::CAmTimerCb::timer3Callback(sh_timerHandle_t, void* userData)
+CAmTimer::CAmTimer(CAmSocketHandler *myHandler, const timespec &timeout, const int32_t repeats) :
+ MockIAmTimerCb(), mpSocketHandler(myHandler), mUpdateTimeout(timeout), pTimerCallback(this, &CAmTimer::timerCallback), mRepeats(repeats)
{
- (void) userData;
- std::cout << "callback3 called" << std::endl;
}
-void am::CAmTimerCb::timer4Callback(sh_timerHandle_t, void* userData)
+am::CAmTimer::~CAmTimer()
{
- (void) userData;
- std::cout << "callback4 called" << std::endl;
- mSocketHandler->stop_listening();
+}
+
+void am::CAmTimer::timerCallback(sh_timerHandle_t handle, void* userData)
+{
+ MockIAmTimerCb::timerCallback(handle, userData);
+ if (--mRepeats > 0)
+ {
+#ifndef WITH_TIMERFD
+ mpSocketHandler->updateTimer( handle, mUpdateTimeout);
+#endif
+ }
+ else
+ {
+ mpSocketHandler->stopTimer(handle);
+ }
+}
+
+CAmTimerMeasurment::CAmTimerMeasurment(CAmSocketHandler *myHandler, const timespec &timeout, const std::string & label, const int32_t repeats, void * userData) :
+ MockIAmTimerCb(), pTimerCallback(this, &CAmTimerMeasurment::timerCallback), //
+ mSocketHandler(myHandler), mUpdateTimeout(timeout), mUpdateTimePoint(std::chrono::seconds
+ { mUpdateTimeout.tv_sec } + std::chrono::nanoseconds
+ { mUpdateTimeout.tv_nsec }), mLastInvocationTime(), mExpected(mUpdateTimePoint - TP_ZERO), mRepeats(repeats), mpUserData(userData), mDebugText(label)
+{
+}
+
+am::CAmTimerMeasurment::~CAmTimerMeasurment()
+{
+}
+
+void am::CAmTimerMeasurment::timerCallback(sh_timerHandle_t handle, void* userData)
+{
+ MockIAmTimerCb::timerCallback(handle, userData);
+
+ std::chrono::time_point < std::chrono::high_resolution_clock > t_end = std::chrono::high_resolution_clock::now();
+ if (TP_ZERO != mLastInvocationTime)
+ {
+ auto durationLast = t_end - mLastInvocationTime;
+ double diff = (std::chrono::duration<double, std::milli>(mExpected - durationLast).count());
+
+#ifdef ENABLED_TIMERS_TEST_OUTPUT
+ std::cout << mDebugText <<
+ " [ expected:" <<std::chrono::duration<double, std::milli>(mExpected).count() << "ms"
+ " , current:" << std::chrono::duration<double, std::milli>(durationLast).count() << "ms"
+ ", diff:" << diff << "ms ] " <<
+ std::endl;
+#endif
+ EXPECT_LT(diff, TIMERS_CB_TOLERANCE) << mDebugText << " [ expected:" << std::chrono::duration<double, std::milli>(mExpected).count() << "ms, current:" << std::chrono::duration<double, std::milli>(durationLast).count() << "ms ]";
+ EXPECT_GT(diff, -TIMERS_CB_TOLERANCE) << mDebugText << " [ expected:" << std::chrono::duration<double, std::milli>(mExpected).count() << "ms, current:" << std::chrono::duration<double, std::milli>(durationLast).count() << "ms ]";
+
+ mLastInvocationTime = t_end;
+ if (--mRepeats > 0)
+ {
+#ifndef WITH_TIMERFD
+ mSocketHandler->updateTimer( handle, mUpdateTimeout);
+#endif
+ }
+ else
+ {
+ mSocketHandler->stopTimer(handle);
+ }
+ }
+ else
+ {
+#ifdef ENABLED_TIMERS_TEST_OUTPUT
+ std::cout << mDebugText << " Init measurment " << std::endl;
+#endif
+ mLastInvocationTime = t_end;
+ mSocketHandler->updateTimer(handle, mUpdateTimeout);
+ }
+
}
void* playWithSocketServer(void* data)
{
- (void) data;
- CAmSocketHandler myHandler;
- CAmSamplePlugin::sockType_e type = CAmSamplePlugin::INET;
- CAmSamplePlugin myplugin(&myHandler, type);
- myHandler.start_listenting();
+ CAmSocketHandler *pSockethandler = (CAmSocketHandler*) data;
+ pSockethandler->start_listenting();
return (NULL);
}
void* playWithUnixSocketServer(void* data)
{
- (void) data;
+ CAmSocketHandler *pSockethandler = (CAmSocketHandler*) data;
+ pSockethandler->start_listenting();
+ return (NULL);
+}
+
+TEST(CAmSocketHandlerTest, timersOneshot)
+{
CAmSocketHandler myHandler;
- CAmSamplePlugin::sockType_e type = CAmSamplePlugin::UNIX;
- CAmSamplePlugin myplugin(&myHandler, type);
+ timespec timeoutTime;
+ timeoutTime.tv_sec = 1;
+ timeoutTime.tv_nsec = 0;
+ CAmTimer testCallback1(&myHandler, timeoutTime);
+
+ struct TestUserData
+ {
+ int i;
+ float f;
+ };
+ TestUserData userData;
+ userData.i = 1;
+ userData.f = 1.f;
+
+ sh_timerHandle_t handle;
+ myHandler.addTimer(timeoutTime, &testCallback1.pTimerCallback, handle, &userData);
+
+ EXPECT_CALL(testCallback1,timerCallback(handle,&userData)).Times(1);
+
+ timespec timeout4;
+ timeout4.tv_nsec = 0;
+ timeout4.tv_sec = 3;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
+ myHandler.start_listenting();
+}
+
+TEST(CAmSocketHandlerTest, timersStop)
+{
+ CAmSocketHandler myHandler;
+ timespec timeoutTime;
+ timeoutTime.tv_sec = 1;
+ timeoutTime.tv_nsec = 0;
+ CAmTimer testCallback1(&myHandler, timeoutTime, 4);
+
+ struct TestUserData
+ {
+ int i;
+ float f;
+ };
+ TestUserData userData;
+ userData.i = 1;
+ userData.f = 1.f;
+
+ sh_timerHandle_t handle;
+ myHandler.addTimer(timeoutTime, &testCallback1.pTimerCallback, handle, &userData, true);
+
+ EXPECT_CALL(testCallback1,timerCallback(handle,&userData)).Times(4);
+
+ timespec timeout4;
+ timeout4.tv_nsec = 0;
+ timeout4.tv_sec = 6;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
+ myHandler.start_listenting();
+}
+
+TEST(CAmSocketHandlerTest, timersGeneral)
+{
+ CAmSocketHandler myHandler;
+ timespec timeoutTime;
+ timeoutTime.tv_sec = 1;
+ timeoutTime.tv_nsec = 0;
+ CAmTimer testCallback1(&myHandler, timeoutTime, 4);
+
+ struct TestUserData
+ {
+ int i;
+ float f;
+ };
+ TestUserData userData;
+ userData.i = 1;
+ userData.f = 1.f;
+
+ sh_timerHandle_t handle;
+ myHandler.addTimer(timeoutTime, &testCallback1.pTimerCallback, handle, &userData, true);
+
+ EXPECT_CALL(testCallback1,timerCallback(handle,&userData)).Times(4); //+1 because of measurment
+
+ timespec timeout4;
+ timeout4.tv_nsec = 0;
+ timeout4.tv_sec = 5;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
myHandler.start_listenting();
- return (NULL);
}
TEST(CAmSocketHandlerTest,playWithTimers)
{
CAmSocketHandler myHandler;
- CAmTimerCb testCallback(&myHandler);
+
timespec timeoutTime, timeout2, timeout3, timeout4;
timeoutTime.tv_sec = 1;
- timeoutTime.tv_nsec = 02223234;
- timeout2.tv_nsec = 333000;
+ timeoutTime.tv_nsec = 34000000;
+ CAmTimerMeasurment testCallback1(&myHandler, timeoutTime, "repeatedCallback 1", std::numeric_limits<int32_t>::max());
+
+ timeout2.tv_nsec = 2000000;
timeout2.tv_sec = 0;
- timeout3.tv_nsec = 333;
+ CAmTimerMeasurment testCallback2(&myHandler, timeout2, "repeatedCallback 2", std::numeric_limits<int32_t>::max());
+
+ timeout3.tv_nsec = 333000000;
timeout3.tv_sec = 3;
+ CAmTimerMeasurment testCallback3(&myHandler, timeout3, "oneshotCallback 3");
timeout4.tv_nsec = 0;
- timeout4.tv_sec = 20;
+ timeout4.tv_sec = 8;
+ CAmTimerSockethandlerController testCallback4(&myHandler, timeout4);
+
sh_timerHandle_t handle;
- myHandler.addTimer(timeoutTime, &testCallback.pTimer1Callback, handle, NULL);
- myHandler.addTimer(timeout2, &testCallback.pTimer2Callback, handle, NULL);
- myHandler.addTimer(timeout3, &testCallback.pTimer3Callback, handle, NULL);
- myHandler.addTimer(timeout4, &testCallback.pTimer4Callback, handle, NULL);
- myHandler.start_listenting();
+ myHandler.addTimer(timeoutTime, &testCallback1.pTimerCallback, handle, NULL, true);
+ EXPECT_CALL(testCallback1,timerCallback(handle,NULL)).Times(AnyNumber());
-}
+ myHandler.addTimer(timeout2, &testCallback2.pTimerCallback, handle, NULL, true);
+ EXPECT_CALL(testCallback2,timerCallback(handle,NULL)).Times(AnyNumber());
+ myHandler.addTimer(timeout3, &testCallback3.pTimerCallback, handle, NULL);
+ EXPECT_CALL(testCallback3,timerCallback(handle,NULL)).Times(2); //+1 because of measurment
+
+ myHandler.addTimer(timeout4, &testCallback4.pTimerCallback, handle, NULL);
+ EXPECT_CALL(testCallback4,timerCallback(handle,NULL)).Times(1);
+
+ myHandler.start_listenting();
+}
TEST(CAmSocketHandlerTest,playWithUNIXSockets)
{
@@ -146,8 +311,16 @@ TEST(CAmSocketHandlerTest,playWithUNIXSockets)
struct sockaddr_un servAddr;
int socket_;
+ CAmSocketHandler myHandler;
+ CAmSamplePlugin::sockType_e type = CAmSamplePlugin::UNIX;
+ CAmSamplePlugin myplugin(&myHandler, type);
+
+ EXPECT_CALL(myplugin,receiveData(_,_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+ EXPECT_CALL(myplugin,dispatchData(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+ EXPECT_CALL(myplugin,check(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+
//creates a thread that handles the serverpart
- pthread_create(&serverThread, NULL, playWithUnixSocketServer, NULL);
+ pthread_create(&serverThread, NULL, playWithUnixSocketServer, &myHandler);
sleep(1); //we need that here because the port needs to be opened
if ((socket_ = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
@@ -164,15 +337,16 @@ TEST(CAmSocketHandlerTest,playWithUNIXSockets)
std::cout << "ERROR: connect() failed\n" << std::endl;
}
- for (int i = 0; i <= 1000; i++)
+ for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++)
{
- std::string string("Got It?");
- send(socket_, string.c_str(), string.size(), 0);
+ std::string stringToSend(TEST_SOCKET_DATA);
+ send(socket_, stringToSend.c_str(), stringToSend.size(), 0);
}
- std::string string("finish!");
- send(socket_, string.c_str(), string.size(), 0);
+ std::string stringToSend(TEST_SOCKET_DATA_FINAL);
+ send(socket_, stringToSend.c_str(), stringToSend.size(), 0);
pthread_join(serverThread, NULL);
+
}
TEST(CAmSocketHandlerTest,playWithSockets)
@@ -183,8 +357,16 @@ TEST(CAmSocketHandlerTest,playWithSockets)
struct hostent *host;
int socket_;
+ CAmSocketHandler myHandler;
+ CAmSamplePlugin::sockType_e type = CAmSamplePlugin::INET;
+ CAmSamplePlugin myplugin(&myHandler, type);
+
+ EXPECT_CALL(myplugin,receiveData(_,_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+ EXPECT_CALL(myplugin,dispatchData(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+ EXPECT_CALL(myplugin,check(_,_)).Times(SOCKET_TEST_LOOPS_COUNT + 1);
+
//creates a thread that handles the serverpart
- pthread_create(&serverThread, NULL, playWithSocketServer, NULL);
+ pthread_create(&serverThread, NULL, playWithSocketServer, &myHandler);
sleep(1); //we need that here because the port needs to be opened
if ((socket_ = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
@@ -209,24 +391,16 @@ TEST(CAmSocketHandlerTest,playWithSockets)
std::cout << "ERROR: connect() failed\n" << std::endl;
}
- for (int i = 0; i <= 1000; i++)
+ for (int i = 1; i <= SOCKET_TEST_LOOPS_COUNT; i++)
{
- std::string string("Got It?");
+ std::string string(TEST_SOCKET_DATA);
send(socket_, string.c_str(), string.size(), 0);
}
- std::string string("finish!");
+ std::string string(TEST_SOCKET_DATA_FINAL);
send(socket_, string.c_str(), string.size(), 0);
pthread_join(serverThread, NULL);
-}
-
-void CAmSocketHandlerTest::SetUp()
-{
-}
-
-void CAmSocketHandlerTest::TearDown()
-{
}
int main(int argc, char **argv)
@@ -236,14 +410,14 @@ int main(int argc, char **argv)
}
am::CAmSamplePlugin::CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType_e socketType) :
- connectFiredCB(this, &CAmSamplePlugin::connectSocket), //
+ MockSocketHandlerCb(), connectFiredCB(this, &CAmSamplePlugin::connectSocket), //
receiveFiredCB(this, &CAmSamplePlugin::receiveData), //
sampleDispatchCB(this, &CAmSamplePlugin::dispatchData), //
sampleCheckCB(this, &CAmSamplePlugin::check), //
mSocketHandler(mySocketHandler), //
mConnecthandle(), //
- mReceiveHandle(), //
- msgList()
+ mReceiveHandle(), //
+ msgList()
{
int yes = 1;
@@ -254,29 +428,31 @@ am::CAmSamplePlugin::CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType
switch (socketType)
{
- case UNIX:
- socketHandle = socket(AF_UNIX, SOCK_STREAM, 0);
- unixAddr.sun_family = AF_UNIX;
- strcpy(unixAddr.sun_path, SOCK_PATH);
- unlink(unixAddr.sun_path);
- bind(socketHandle, (struct sockaddr *) &unixAddr, strlen(unixAddr.sun_path) + sizeof(unixAddr.sun_family));
- break;
- case INET:
- socketHandle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
- setsockopt(socketHandle, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
- memset(&servAddr, 0, sizeof(servAddr));
- servAddr.sin_family = AF_INET;
- servAddr.sin_addr.s_addr = INADDR_ANY;
- servAddr.sin_port = htons(servPort);
- bind(socketHandle, (struct sockaddr *) &servAddr, sizeof(servAddr));
- break;
- default:
- break;
+ case UNIX:
+ socketHandle = socket(AF_UNIX, SOCK_STREAM, 0);
+ unixAddr.sun_family = AF_UNIX;
+ strcpy(unixAddr.sun_path, SOCK_PATH);
+ unlink(unixAddr.sun_path);
+ bind(socketHandle, (struct sockaddr *) &unixAddr, strlen(unixAddr.sun_path) + sizeof(unixAddr.sun_family));
+ break;
+ case INET:
+ socketHandle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ setsockopt(socketHandle, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int));
+ memset(&servAddr, 0, sizeof(servAddr));
+ servAddr.sin_family = AF_INET;
+ servAddr.sin_addr.s_addr = INADDR_ANY;
+ servAddr.sin_port = htons(servPort);
+ bind(socketHandle, (struct sockaddr *) &servAddr, sizeof(servAddr));
+ break;
+ default:
+ break;
}
if (listen(socketHandle, 3) < 0)
{
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "listen ok" << std::endl;
+#endif
} /* if */
int a = 1;
@@ -286,7 +462,9 @@ am::CAmSamplePlugin::CAmSamplePlugin(CAmSocketHandler *mySocketHandler, sockType
short events = 0;
events |= POLLIN;
mySocketHandler->addFDPoll(socketHandle, events, NULL, &connectFiredCB, NULL, NULL, NULL, mConnecthandle);
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "setup server - listening" << std::endl;
+#endif
}
void am::CAmSamplePlugin::connectSocket(const pollfd pollfd1, const sh_pollHandle_t handle, void *userData)
@@ -294,7 +472,9 @@ void am::CAmSamplePlugin::connectSocket(const pollfd pollfd1, const sh_pollHandl
(void) handle;
(void) userData;
//first, accept the connection, create a new filedescriptor
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "Got a connection request !" << std::endl;
+#endif
struct sockaddr answer;
socklen_t len = sizeof(answer);
int receiveFD = accept(pollfd1.fd, (struct sockaddr*) &answer, &len);
@@ -312,6 +492,7 @@ void am::CAmSamplePlugin::receiveData(const pollfd pollfd, const sh_pollHandle_t
{
(void) handle;
(void) userData;
+ MockSocketHandlerCb::receiveData(pollfd, handle, userData);
//initialize buffer
char buffer[10];
//read until buffer is full or no more data is there
@@ -321,7 +502,9 @@ void am::CAmSamplePlugin::receiveData(const pollfd pollfd, const sh_pollHandle_t
//read the message and store it in a queue
std::string msg = std::string(buffer, read);
msgList.push(msg);
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "Got a message !" << std::endl;
+#endif
}
}
@@ -330,13 +513,20 @@ bool am::CAmSamplePlugin::dispatchData(const sh_pollHandle_t handle, void *userD
(void) handle;
(void) userData;
//read data from the queue
+ MockSocketHandlerCb::dispatchData(handle, userData);
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "Data:" << msgList.front() << std::endl;
-
+#endif
//if the message was our finish message, we quit the poll loop
- if (msgList.front().compare("finish!") == 0)
+ if (!(msgList.front().compare(TEST_SOCKET_DATA_FINAL) == 0 || msgList.front().compare(TEST_SOCKET_DATA) == 0)) //error
{
mSocketHandler->stop_listening();
}
+ if (msgList.front().compare(TEST_SOCKET_DATA_FINAL) == 0) //ok
+ {
+ mSocketHandler->stop_listening();
+ }
+
//remove the message from the queue and return false if there is no more message to read.
msgList.pop();
if (msgList.size() != 0)
@@ -348,8 +538,11 @@ bool am::CAmSamplePlugin::check(const sh_pollHandle_t handle, void *userData)
{
(void) handle;
(void) userData;
+ MockSocketHandlerCb::check(handle, userData);
//checks if there is data to dispatch
+#ifdef ENABLED_SOCKETHANDLER_TEST_OUTPUT
std::cout << "check!:" << std::endl;
+#endif
if (msgList.size() != 0)
return true;
return false;
diff --git a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h
index 95e5446..b7d2a09 100644
--- a/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h
+++ b/AudioManagerUtilities/test/AmSocketHandlerTest/CAmSocketHandlerTest.h
@@ -25,14 +25,52 @@
#define WITH_DLT
+#include <ctime>
+#include <chrono>
#include "gtest/gtest.h"
+#include "gmock/gmock.h"
#include <queue>
#include "CAmSocketHandler.h"
+#undef ENABLED_SOCKETHANDLER_TEST_OUTPUT
+#undef ENABLED_TIMERS_TEST_OUTPUT
+#define TIMERS_CB_TOLERANCE 10.f
+
namespace am
{
+ class IAmTimerCb
+ {
+ public:
+ virtual void timerCallback(sh_timerHandle_t handle, void * userData)=0;
+ };
+
+ class IAmSocketHandlerCb
+ {
+ public:
+ virtual void receiveData(const pollfd pollfd, const sh_pollHandle_t handle, void* userData)=0;
+ virtual bool dispatchData(const sh_pollHandle_t handle, void* userData)=0;
+ virtual bool check(const sh_pollHandle_t handle, void* userData)=0;
+ };
-class CAmSamplePlugin
+ class MockIAmTimerCb : public IAmTimerCb
+ {
+ public:
+ MOCK_CONST_METHOD2(timerCallback,
+ void(sh_timerHandle_t handle, void *userData));
+ };
+
+ class MockSocketHandlerCb : public IAmSocketHandlerCb
+ {
+ public:
+ MOCK_CONST_METHOD3(receiveData,
+ void(const pollfd pollfd, const sh_pollHandle_t handle, void* userData));
+ MOCK_CONST_METHOD2(dispatchData,
+ void(const sh_pollHandle_t handle, void* userData));
+ MOCK_CONST_METHOD2(check,
+ void(const sh_pollHandle_t handle, void* userData));
+ };
+
+class CAmSamplePlugin : public MockSocketHandlerCb
{
public:
enum sockType_e
@@ -52,26 +90,56 @@ public:
TAmShPollFired<CAmSamplePlugin> receiveFiredCB;
TAmShPollDispatch<CAmSamplePlugin> sampleDispatchCB;
TAmShPollCheck<CAmSamplePlugin> sampleCheckCB;
+
private:
CAmSocketHandler *mSocketHandler;
sh_pollHandle_t mConnecthandle, mReceiveHandle;
std::queue<std::string> msgList;
};
-class CAmTimerCb
+class CAmTimerSockethandlerController: public MockIAmTimerCb
+{
+ CAmSocketHandler *mpSocketHandler;
+ timespec mUpdateTimeout;
+public:
+ explicit CAmTimerSockethandlerController(CAmSocketHandler *SocketHandler, const timespec &timeout);
+ virtual ~CAmTimerSockethandlerController();
+
+ void timerCallback(sh_timerHandle_t handle, void * userData);
+
+ TAmShTimerCallBack<CAmTimerSockethandlerController> pTimerCallback;
+};
+
+class CAmTimer: public MockIAmTimerCb
{
+ CAmSocketHandler *mpSocketHandler;
+ timespec mUpdateTimeout;
+ int32_t mRepeats;
public:
- CAmTimerCb(CAmSocketHandler *SocketHandler);
- virtual ~CAmTimerCb();
- void timer1Callback(sh_timerHandle_t handle, void * userData);
- void timer2Callback(sh_timerHandle_t handle, void * userData);
- void timer3Callback(sh_timerHandle_t handle, void * userData);
- void timer4Callback(sh_timerHandle_t handle, void * userData);
- TAmShTimerCallBack<CAmTimerCb> pTimer1Callback;
- TAmShTimerCallBack<CAmTimerCb> pTimer2Callback;
- TAmShTimerCallBack<CAmTimerCb> pTimer3Callback;
- TAmShTimerCallBack<CAmTimerCb> pTimer4Callback;
+ explicit CAmTimer(CAmSocketHandler *SocketHandler, const timespec &timeout, const int32_t repeats = 0u);
+ virtual ~CAmTimer();
+
+ void timerCallback(sh_timerHandle_t handle, void * userData);
+
+ TAmShTimerCallBack<CAmTimer> pTimerCallback;
+};
+
+class CAmTimerMeasurment: public MockIAmTimerCb
+{
CAmSocketHandler *mSocketHandler;
+ timespec mUpdateTimeout;
+ std::chrono::time_point<std::chrono::high_resolution_clock> mUpdateTimePoint;
+ std::chrono::time_point<std::chrono::high_resolution_clock> mLastInvocationTime;
+ std::chrono::duration<long, std::ratio<1l, 1000000000l>> mExpected;
+ int32_t mRepeats;
+ void * mpUserData;
+ std::string mDebugText;
+public:
+ explicit CAmTimerMeasurment(CAmSocketHandler *SocketHandler, const timespec &timeout, const std::string & label, const int32_t repeats = 0u, void * userData = NULL);
+ virtual ~CAmTimerMeasurment();
+
+ void timerCallback(sh_timerHandle_t handle, void * userData);
+ TAmShTimerCallBack<CAmTimerMeasurment> pTimerCallback;
};
class CAmSocketHandlerTest: public ::testing::Test