diff --git a/server/modules/filter/dbfwfilter/test/maxscale/mock/backend.hh b/server/modules/filter/dbfwfilter/test/maxscale/mock/backend.hh index b0fea2a80..5cfdf35d3 100644 --- a/server/modules/filter/dbfwfilter/test/maxscale/mock/backend.hh +++ b/server/modules/filter/dbfwfilter/test/maxscale/mock/backend.hh @@ -59,6 +59,22 @@ public: */ virtual bool idle(const RouterSession* pSession) const = 0; + /** + * Discards an available response. + * + * @param pSession A router session. + * + * @return True if there are additional responses for the router session. + */ + virtual bool discard_one_response(const RouterSession* pSession) = 0; + + /** + * Discards all available responses. + * + * @param pSession A router session. + */ + virtual void discard_all_responses(const RouterSession* pSession) = 0; + protected: Backend(); }; @@ -79,6 +95,10 @@ public: bool idle(const RouterSession* pSession) const; + bool discard_one_response(const RouterSession* pSession); + + void discard_all_responses(const RouterSession* pSession); + protected: BufferBackend(); @@ -88,7 +108,10 @@ protected: * @param pSession The session to enqueue the response for. * @param pResponse The response. */ - void enqueue_response(RouterSession* pSession, GWBUF* pResponse); + void enqueue_response(const RouterSession* pSession, GWBUF* pResponse); + +private: + GWBUF* dequeue_response(const RouterSession* pSession, bool* pEmpty); private: typedef std::deque Responses; diff --git a/server/modules/filter/dbfwfilter/test/maxscale/mock/dcb.hh b/server/modules/filter/dbfwfilter/test/maxscale/mock/dcb.hh index 6ab2b9429..21f0c8fa4 100644 --- a/server/modules/filter/dbfwfilter/test/maxscale/mock/dcb.hh +++ b/server/modules/filter/dbfwfilter/test/maxscale/mock/dcb.hh @@ -31,18 +31,42 @@ class Dcb : public DCB Dcb& operator = (const Dcb&); public: + class Handler + { + public: + virtual int32_t write(GWBUF* pBuffer) = 0; + }; + /** * Constructor * * @param pSession The session object of the DCB. * @param zUser The client of the connection. * @param zHost The host of the connection. + * @param pHandler Optional handler. */ Dcb(MXS_SESSION* pSession, const char* zUser, - const char* zHost); + const char* zHost, + Handler* pHandler = NULL); ~Dcb(); + /** + * Get the current handler of the Dcb. + * + * @return A Handler or NULL. + */ + Handler* handler() const; + + /** + * Set the current handler of the Dcb. + * + * @param pHandler The new handler. + * + * @return The previous handler or NULL. + */ + Handler* set_handler(Handler* pHandler); + private: int32_t write(GWBUF* pData); @@ -51,6 +75,7 @@ private: private: std::string m_user; std::string m_host; + Handler* m_pHandler; }; } diff --git a/server/modules/filter/dbfwfilter/test/maxscale/mock/routersession.hh b/server/modules/filter/dbfwfilter/test/maxscale/mock/routersession.hh index 744dd3e39..e3690315a 100644 --- a/server/modules/filter/dbfwfilter/test/maxscale/mock/routersession.hh +++ b/server/modules/filter/dbfwfilter/test/maxscale/mock/routersession.hh @@ -78,6 +78,18 @@ public: */ bool idle() const; + /** + * Discards one response. + * + * @return True, if there are additional responses. + */ + bool discard_one_response(); + + /** + * Discards all responses. + */ + void discard_all_responses(); + private: int32_t routeQuery(MXS_ROUTER* pInstance, GWBUF* pStatement); diff --git a/server/modules/filter/dbfwfilter/test/maxscale/mock/session.hh b/server/modules/filter/dbfwfilter/test/maxscale/mock/session.hh index 6393fe2cb..62ef14b65 100644 --- a/server/modules/filter/dbfwfilter/test/maxscale/mock/session.hh +++ b/server/modules/filter/dbfwfilter/test/maxscale/mock/session.hh @@ -36,11 +36,13 @@ public: /** * Constructor * - * @param zUser The client of the session, - * @param zHost The host of the client. + * @param zUser The client of the session, + * @param zHost The host of the client. + * @param pHandler Handler for the client Dcb. */ - Session(const char* zUser, - const char* zHost = "127.0.0.1"); + Session(const char* zUser, + const char* zHost, + Dcb::Handler* pHandler = NULL); ~Session(); private: diff --git a/server/modules/filter/dbfwfilter/test/maxscale/mock/upstream.hh b/server/modules/filter/dbfwfilter/test/maxscale/mock/upstream.hh index ed800b380..500e71489 100644 --- a/server/modules/filter/dbfwfilter/test/maxscale/mock/upstream.hh +++ b/server/modules/filter/dbfwfilter/test/maxscale/mock/upstream.hh @@ -16,6 +16,7 @@ #include #include #include "../filtermodule.hh" +#include "dcb.hh" namespace maxscale { @@ -27,6 +28,7 @@ namespace mock * An instance of Upstream represents an upstream object of a filter. */ class Upstream : public MXS_FILTER_SESSION + , public Dcb::Handler { Upstream(const Upstream&); Upstream& operator = (const Upstream&); @@ -47,7 +49,16 @@ public: * * @return 1 if processing should continue, 0 otherwise. */ - virtual int32_t clientReply(GWBUF* pResponse) = 0; + virtual int32_t backend_reply(GWBUF* pResponse) = 0; + + /** + * Called when a response is sent directly by a filter. + * + * @param pResponse The response packet. + * + * @return 1 if processing should continue, 0 otherwise. + */ + virtual int32_t maxscale_reply(GWBUF* pResponse) = 0; /** * Called when @reset is called on the @c Upstream instance. @@ -98,6 +109,9 @@ private: static int32_t clientReply(MXS_FILTER* pInstance, MXS_FILTER_SESSION* pSession, GWBUF* pResponse); + // Dcb::Handler + int32_t write(GWBUF* pBuffer); + private: MXS_FILTER m_instance; Handler* m_pHandler; diff --git a/server/modules/filter/dbfwfilter/test/mock_backend.cc b/server/modules/filter/dbfwfilter/test/mock_backend.cc index 909c90c8f..2e179913b 100644 --- a/server/modules/filter/dbfwfilter/test/mock_backend.cc +++ b/server/modules/filter/dbfwfilter/test/mock_backend.cc @@ -12,6 +12,7 @@ */ #include "maxscale/mock/backend.hh" +#include #include #include @@ -48,24 +49,15 @@ BufferBackend::~BufferBackend() bool BufferBackend::respond(RouterSession* pSession) { - ss_dassert(!idle(pSession)); + bool empty = false; + GWBUF* pResponse = dequeue_response(pSession, &empty); - bool rv = false; - - if (!idle(pSession)) + if (pResponse) { - Responses& responses = m_session_responses[pSession]; - ss_dassert(!responses.empty()); - - GWBUF* pResponse = responses.front(); - responses.pop_front(); - pSession->clientReply(pResponse); - - rv = !responses.empty(); } - return rv; + return !empty; } bool BufferBackend::idle(const RouterSession* pSession) const @@ -83,13 +75,59 @@ bool BufferBackend::idle(const RouterSession* pSession) const return rv; } -void BufferBackend::enqueue_response(RouterSession* pSession, GWBUF* pResponse) +bool BufferBackend::discard_one_response(const RouterSession* pSession) +{ + bool empty = false; + gwbuf_free(dequeue_response(pSession, &empty)); + + return !empty; +} + +void BufferBackend::discard_all_responses(const RouterSession* pSession) +{ + ss_dassert(!idle(pSession)); + + if (!idle(pSession)) + { + Responses& responses = m_session_responses[pSession]; + ss_dassert(!responses.empty()); + + std::for_each(responses.begin(), responses.end(), gwbuf_free); + responses.clear(); + } +} + +void BufferBackend::enqueue_response(const RouterSession* pSession, GWBUF* pResponse) { Responses& responses = m_session_responses[pSession]; responses.push_back(pResponse); } +GWBUF* BufferBackend::dequeue_response(const RouterSession* pSession, bool* pEmpty) +{ + ss_dassert(!idle(pSession)); + GWBUF* pResponse = NULL; + *pEmpty = true; + + if (!idle(pSession)) + { + Responses& responses = m_session_responses[pSession]; + ss_dassert(!responses.empty()); + + if (!responses.empty()) + { + pResponse = responses.front(); + responses.pop_front(); + } + + *pEmpty = responses.empty(); + } + + return pResponse; +} + + // // OkBackend // diff --git a/server/modules/filter/dbfwfilter/test/mock_dcb.cc b/server/modules/filter/dbfwfilter/test/mock_dcb.cc index 5483f8886..7de9887d2 100644 --- a/server/modules/filter/dbfwfilter/test/mock_dcb.cc +++ b/server/modules/filter/dbfwfilter/test/mock_dcb.cc @@ -37,9 +37,11 @@ namespace mock Dcb::Dcb(MXS_SESSION* pSession, const char* zUser, - const char* zHost) + const char* zHost, + Handler* pHandler) : m_user(zUser) , m_host(zHost) + , m_pHandler(pHandler) { DCB* pDcb = this; initialize_dcb(this); @@ -55,11 +57,32 @@ Dcb::~Dcb() { } +Dcb::Handler* Dcb::handler() const +{ + return m_pHandler; +} + +Dcb::Handler* Dcb::set_handler(Handler* pHandler) +{ + Handler* p = m_pHandler; + m_pHandler = pHandler; + return p; +} + int32_t Dcb::write(GWBUF* pData) { - // TODO: Should be routed somewhere - gwbuf_free(pData); - return 1; + int32_t rv = 1; + + if (m_pHandler) + { + rv = m_pHandler->write(pData); + } + else + { + gwbuf_free(pData); + } + + return rv; } //static diff --git a/server/modules/filter/dbfwfilter/test/mock_routersession.cc b/server/modules/filter/dbfwfilter/test/mock_routersession.cc index 40d797318..79ebff20f 100644 --- a/server/modules/filter/dbfwfilter/test/mock_routersession.cc +++ b/server/modules/filter/dbfwfilter/test/mock_routersession.cc @@ -52,6 +52,16 @@ bool RouterSession::idle() const return m_pBackend->idle(this); } +bool RouterSession::discard_one_response() +{ + return m_pBackend->discard_one_response(this); +} + +void RouterSession::discard_all_responses() +{ + return m_pBackend->discard_all_responses(this); +} + int32_t RouterSession::routeQuery(MXS_ROUTER* pInstance, GWBUF* pStatement) { ss_dassert(pInstance == &m_instance); diff --git a/server/modules/filter/dbfwfilter/test/mock_session.cc b/server/modules/filter/dbfwfilter/test/mock_session.cc index f0d62ea4c..74ea4878c 100644 --- a/server/modules/filter/dbfwfilter/test/mock_session.cc +++ b/server/modules/filter/dbfwfilter/test/mock_session.cc @@ -19,9 +19,10 @@ namespace maxscale namespace mock { -Session::Session(const char* zUser, - const char* zHost) - : m_client_dcb(this, zUser, zHost) +Session::Session(const char* zUser, + const char* zHost, + Dcb::Handler* pHandler) + : m_client_dcb(this, zUser, zHost, pHandler) { MXS_SESSION* pSession = this; diff --git a/server/modules/filter/dbfwfilter/test/mock_upstream.cc b/server/modules/filter/dbfwfilter/test/mock_upstream.cc index ccb1c2364..f89f47b7f 100644 --- a/server/modules/filter/dbfwfilter/test/mock_upstream.cc +++ b/server/modules/filter/dbfwfilter/test/mock_upstream.cc @@ -67,13 +67,31 @@ void Upstream::set_as_upstream_on(FilterModule::Session& filter_session) int32_t Upstream::clientReply(GWBUF* pResponse) { - int rv = 1; + int32_t rv = 1; ++m_n_responses; if (m_pHandler) { - rv = m_pHandler->clientReply(pResponse); + rv = m_pHandler->backend_reply(pResponse); + } + else + { + gwbuf_free(pResponse); + } + + return rv; +} + +int32_t Upstream::write(GWBUF* pResponse) +{ + int32_t rv = 1; + + ++m_n_responses; + + if (m_pHandler) + { + rv = m_pHandler->maxscale_reply(pResponse); } else { diff --git a/server/modules/filter/dbfwfilter/test/test_dbfwfilter.cc b/server/modules/filter/dbfwfilter/test/test_dbfwfilter.cc index 2afcd3dcc..65147954a 100644 --- a/server/modules/filter/dbfwfilter/test/test_dbfwfilter.cc +++ b/server/modules/filter/dbfwfilter/test/test_dbfwfilter.cc @@ -136,7 +136,7 @@ int test(FilterModule::Session& filter_session, { if (!router_session.idle()) // Statement reached backend { - router_session.respond(); // To discard. TODO: Provide router_session.discard(). + router_session.discard_one_response(); log_success(c); } else @@ -155,7 +155,7 @@ int test(FilterModule::Session& filter_session, } else { - router_session.respond(); + router_session.discard_one_response(); log_error(c); rv = 1; } @@ -177,7 +177,8 @@ int test(FilterModule::Instance& filter_instance, const FW_TEST& t) if (c.zStatement) { - mock::Session session(c.zUser, c.zHost); + mock::Upstream upstream; + mock::Session session(c.zUser, c.zHost, &upstream); auto_ptr sFilter_session = filter_instance.newSession(&session); @@ -185,8 +186,6 @@ int test(FilterModule::Instance& filter_instance, const FW_TEST& t) { router_session.set_as_downstream_on(sFilter_session.get()); - mock::Upstream upstream; - upstream.set_as_upstream_on(*sFilter_session.get()); rv += test(*sFilter_session.get(), router_session, c);