From 99c3edf827a16d4bdc1c40a5df7c18bf8626afa3 Mon Sep 17 00:00:00 2001 From: Aleksandar Donchev Date: Mon, 6 Mar 2017 17:10:32 +0100 Subject: CAmSocketHandler - usage of std::function instead of function pointers, code cleanup and minior optimizations. Signed-off-by: Christian Linke Change-Id: I8c2c2c436ac9abc37c76a12245c731f327cab0e5 --- AudioManagerUtilities/include/CAmSocketHandler.h | 235 ++++--------- AudioManagerUtilities/src/CAmSocketHandler.cpp | 324 +++++++++++------- .../AmSocketHandlerTest/CAmSocketHandlerTest.cpp | 375 ++++++++++++++++----- .../AmSocketHandlerTest/CAmSocketHandlerTest.h | 92 ++++- 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 #include #include +#include #include #include "audiomanagertypes.h" + #ifdef WITH_TIMERFD #include @@ -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; //! 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 //! prepareCB; //preperation callback + std::function firedCB; //fired callback + std::function checkCB; //check callback + std::function dispatchCB; //dispatch callback + void* userData; + + sh_poll_s() : + handle(0), pollfdValue(), prepareCB(), firedCB(), checkCB(), dispatchCB(), userData(0) + { + } }; struct sh_timer_s //! callback; //timer callback + void* userData; + sh_timer_s() : + handle(0) +#ifdef WITH_TIMERFD + , fd(0) +#endif + , countdown(), callback(), userData(0) + { + } }; typedef std::reverse_iterator rListTimerIter; //! mListPollfd_t; //! mListPoll_t; //! VectorListPollfd_t; //! VectorListPoll_t; //!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 prepare, std::function fired, + std::function check, std::function 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 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 mReceiverCallbackT; - TAmShPollCheck mCheckerCallbackT; -#ifdef WITH_TIMERFD - std::list 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 //! mSetPollKeys; //!A set of all used ppoll keys - mListPoll_t mListPoll; //! mSetTimerKeys; //!A set of all used timer keys std::list mListTimer; //! mListActiveTimer; //! 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 listPoll; - mListPoll_t::iterator listmPollIt; - - //remove all filedescriptors who did not fire - std::vector::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, ¤tTime); 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 prepare, + std::function fired, std::function check, + std::function 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); @@ -266,6 +268,38 @@ namespace am return (E_OK); } + /** + * 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 prepareCB; //preperation callback + std::function firedCB; //fired callback + std::function checkCB; //check callback + std::function 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 @@ -273,7 +307,7 @@ namespace am */ 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 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 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, ¤tTime); 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::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, ¤tTime); 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::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownUp(diffTime)); + std::list::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), countdownUp); //copy all fired timers into a list std::vector 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, ¤tTime); 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::reverse_iterator overflowIter = std::find_if(mListActiveTimer.rbegin(), mListActiveTimer.rend(), CAmShCountdownZero()); + std::list::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 #include #include + #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 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(mExpected - durationLast).count()); + +#ifdef ENABLED_TIMERS_TEST_OUTPUT + std::cout << mDebugText << + " [ expected:" <(mExpected).count() << "ms" + " , current:" << std::chrono::duration(durationLast).count() << "ms" + ", diff:" << diff << "ms ] " << + std::endl; +#endif + EXPECT_LT(diff, TIMERS_CB_TOLERANCE) << mDebugText << " [ expected:" << std::chrono::duration(mExpected).count() << "ms, current:" << std::chrono::duration(durationLast).count() << "ms ]"; + EXPECT_GT(diff, -TIMERS_CB_TOLERANCE) << mDebugText << " [ expected:" << std::chrono::duration(mExpected).count() << "ms, current:" << std::chrono::duration(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::max()); + + timeout2.tv_nsec = 2000000; timeout2.tv_sec = 0; - timeout3.tv_nsec = 333; + CAmTimerMeasurment testCallback2(&myHandler, timeout2, "repeatedCallback 2", std::numeric_limits::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 +#include #include "gtest/gtest.h" +#include "gmock/gmock.h" #include #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 receiveFiredCB; TAmShPollDispatch sampleDispatchCB; TAmShPollCheck sampleCheckCB; + private: CAmSocketHandler *mSocketHandler; sh_pollHandle_t mConnecthandle, mReceiveHandle; std::queue 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 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 pTimer1Callback; - TAmShTimerCallBack pTimer2Callback; - TAmShTimerCallBack pTimer3Callback; - TAmShTimerCallBack pTimer4Callback; + explicit CAmTimer(CAmSocketHandler *SocketHandler, const timespec &timeout, const int32_t repeats = 0u); + virtual ~CAmTimer(); + + void timerCallback(sh_timerHandle_t handle, void * userData); + + TAmShTimerCallBack pTimerCallback; +}; + +class CAmTimerMeasurment: public MockIAmTimerCb +{ CAmSocketHandler *mSocketHandler; + timespec mUpdateTimeout; + std::chrono::time_point mUpdateTimePoint; + std::chrono::time_point mLastInvocationTime; + std::chrono::duration> 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 pTimerCallback; }; class CAmSocketHandlerTest: public ::testing::Test -- cgit v1.2.1