MXS-1461 Modify mock classes

This commit is contained in:
Johan Wikman
2017-11-15 16:02:26 +02:00
parent 8fba2a8049
commit a35a4c7e9f
11 changed files with 200 additions and 35 deletions

View File

@ -59,6 +59,22 @@ public:
*/ */
virtual bool idle(const RouterSession* pSession) const = 0; 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: protected:
Backend(); Backend();
}; };
@ -79,6 +95,10 @@ public:
bool idle(const RouterSession* pSession) const; bool idle(const RouterSession* pSession) const;
bool discard_one_response(const RouterSession* pSession);
void discard_all_responses(const RouterSession* pSession);
protected: protected:
BufferBackend(); BufferBackend();
@ -88,7 +108,10 @@ protected:
* @param pSession The session to enqueue the response for. * @param pSession The session to enqueue the response for.
* @param pResponse The response. * @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: private:
typedef std::deque<GWBUF*> Responses; typedef std::deque<GWBUF*> Responses;

View File

@ -31,18 +31,42 @@ class Dcb : public DCB
Dcb& operator = (const Dcb&); Dcb& operator = (const Dcb&);
public: public:
class Handler
{
public:
virtual int32_t write(GWBUF* pBuffer) = 0;
};
/** /**
* Constructor * Constructor
* *
* @param pSession The session object of the DCB. * @param pSession The session object of the DCB.
* @param zUser The client of the connection. * @param zUser The client of the connection.
* @param zHost The host of the connection. * @param zHost The host of the connection.
* @param pHandler Optional handler.
*/ */
Dcb(MXS_SESSION* pSession, Dcb(MXS_SESSION* pSession,
const char* zUser, const char* zUser,
const char* zHost); const char* zHost,
Handler* pHandler = NULL);
~Dcb(); ~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: private:
int32_t write(GWBUF* pData); int32_t write(GWBUF* pData);
@ -51,6 +75,7 @@ private:
private: private:
std::string m_user; std::string m_user;
std::string m_host; std::string m_host;
Handler* m_pHandler;
}; };
} }

View File

@ -78,6 +78,18 @@ public:
*/ */
bool idle() const; 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: private:
int32_t routeQuery(MXS_ROUTER* pInstance, GWBUF* pStatement); int32_t routeQuery(MXS_ROUTER* pInstance, GWBUF* pStatement);

View File

@ -36,11 +36,13 @@ public:
/** /**
* Constructor * Constructor
* *
* @param zUser The client of the session, * @param zUser The client of the session,
* @param zHost The host of the client. * @param zHost The host of the client.
* @param pHandler Handler for the client Dcb.
*/ */
Session(const char* zUser, Session(const char* zUser,
const char* zHost = "127.0.0.1"); const char* zHost,
Dcb::Handler* pHandler = NULL);
~Session(); ~Session();
private: private:

View File

@ -16,6 +16,7 @@
#include <memory> #include <memory>
#include <maxscale/filter.h> #include <maxscale/filter.h>
#include "../filtermodule.hh" #include "../filtermodule.hh"
#include "dcb.hh"
namespace maxscale namespace maxscale
{ {
@ -27,6 +28,7 @@ namespace mock
* An instance of Upstream represents an upstream object of a filter. * An instance of Upstream represents an upstream object of a filter.
*/ */
class Upstream : public MXS_FILTER_SESSION class Upstream : public MXS_FILTER_SESSION
, public Dcb::Handler
{ {
Upstream(const Upstream&); Upstream(const Upstream&);
Upstream& operator = (const Upstream&); Upstream& operator = (const Upstream&);
@ -47,7 +49,16 @@ public:
* *
* @return 1 if processing should continue, 0 otherwise. * @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. * 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); static int32_t clientReply(MXS_FILTER* pInstance, MXS_FILTER_SESSION* pSession, GWBUF* pResponse);
// Dcb::Handler
int32_t write(GWBUF* pBuffer);
private: private:
MXS_FILTER m_instance; MXS_FILTER m_instance;
Handler* m_pHandler; Handler* m_pHandler;

View File

@ -12,6 +12,7 @@
*/ */
#include "maxscale/mock/backend.hh" #include "maxscale/mock/backend.hh"
#include <algorithm>
#include <maxscale/protocol/mysql.h> #include <maxscale/protocol/mysql.h>
#include <iostream> #include <iostream>
@ -48,24 +49,15 @@ BufferBackend::~BufferBackend()
bool BufferBackend::respond(RouterSession* pSession) bool BufferBackend::respond(RouterSession* pSession)
{ {
ss_dassert(!idle(pSession)); bool empty = false;
GWBUF* pResponse = dequeue_response(pSession, &empty);
bool rv = false; if (pResponse)
if (!idle(pSession))
{ {
Responses& responses = m_session_responses[pSession];
ss_dassert(!responses.empty());
GWBUF* pResponse = responses.front();
responses.pop_front();
pSession->clientReply(pResponse); pSession->clientReply(pResponse);
rv = !responses.empty();
} }
return rv; return !empty;
} }
bool BufferBackend::idle(const RouterSession* pSession) const bool BufferBackend::idle(const RouterSession* pSession) const
@ -83,13 +75,59 @@ bool BufferBackend::idle(const RouterSession* pSession) const
return rv; 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& responses = m_session_responses[pSession];
responses.push_back(pResponse); 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 // OkBackend
// //

View File

@ -37,9 +37,11 @@ namespace mock
Dcb::Dcb(MXS_SESSION* pSession, Dcb::Dcb(MXS_SESSION* pSession,
const char* zUser, const char* zUser,
const char* zHost) const char* zHost,
Handler* pHandler)
: m_user(zUser) : m_user(zUser)
, m_host(zHost) , m_host(zHost)
, m_pHandler(pHandler)
{ {
DCB* pDcb = this; DCB* pDcb = this;
initialize_dcb(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) int32_t Dcb::write(GWBUF* pData)
{ {
// TODO: Should be routed somewhere int32_t rv = 1;
gwbuf_free(pData);
return 1; if (m_pHandler)
{
rv = m_pHandler->write(pData);
}
else
{
gwbuf_free(pData);
}
return rv;
} }
//static //static

View File

@ -52,6 +52,16 @@ bool RouterSession::idle() const
return m_pBackend->idle(this); 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) int32_t RouterSession::routeQuery(MXS_ROUTER* pInstance, GWBUF* pStatement)
{ {
ss_dassert(pInstance == &m_instance); ss_dassert(pInstance == &m_instance);

View File

@ -19,9 +19,10 @@ namespace maxscale
namespace mock namespace mock
{ {
Session::Session(const char* zUser, Session::Session(const char* zUser,
const char* zHost) const char* zHost,
: m_client_dcb(this, zUser, zHost) Dcb::Handler* pHandler)
: m_client_dcb(this, zUser, zHost, pHandler)
{ {
MXS_SESSION* pSession = this; MXS_SESSION* pSession = this;

View File

@ -67,13 +67,31 @@ void Upstream::set_as_upstream_on(FilterModule::Session& filter_session)
int32_t Upstream::clientReply(GWBUF* pResponse) int32_t Upstream::clientReply(GWBUF* pResponse)
{ {
int rv = 1; int32_t rv = 1;
++m_n_responses; ++m_n_responses;
if (m_pHandler) 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 else
{ {

View File

@ -136,7 +136,7 @@ int test(FilterModule::Session& filter_session,
{ {
if (!router_session.idle()) // Statement reached backend 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); log_success(c);
} }
else else
@ -155,7 +155,7 @@ int test(FilterModule::Session& filter_session,
} }
else else
{ {
router_session.respond(); router_session.discard_one_response();
log_error(c); log_error(c);
rv = 1; rv = 1;
} }
@ -177,7 +177,8 @@ int test(FilterModule::Instance& filter_instance, const FW_TEST& t)
if (c.zStatement) if (c.zStatement)
{ {
mock::Session session(c.zUser, c.zHost); mock::Upstream upstream;
mock::Session session(c.zUser, c.zHost, &upstream);
auto_ptr<FilterModule::Session> sFilter_session = filter_instance.newSession(&session); auto_ptr<FilterModule::Session> 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()); router_session.set_as_downstream_on(sFilter_session.get());
mock::Upstream upstream;
upstream.set_as_upstream_on(*sFilter_session.get()); upstream.set_as_upstream_on(*sFilter_session.get());
rv += test(*sFilter_session.get(), router_session, c); rv += test(*sFilter_session.get(), router_session, c);