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;
/**
* 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<GWBUF*> Responses;

View File

@ -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;
};
}

View File

@ -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);

View File

@ -38,9 +38,11 @@ public:
*
* @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");
const char* zHost,
Dcb::Handler* pHandler = NULL);
~Session();
private:

View File

@ -16,6 +16,7 @@
#include <memory>
#include <maxscale/filter.h>
#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;

View File

@ -12,6 +12,7 @@
*/
#include "maxscale/mock/backend.hh"
#include <algorithm>
#include <maxscale/protocol/mysql.h>
#include <iostream>
@ -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
//

View File

@ -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
int32_t rv = 1;
if (m_pHandler)
{
rv = m_pHandler->write(pData);
}
else
{
gwbuf_free(pData);
return 1;
}
return rv;
}
//static

View File

@ -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);

View File

@ -20,8 +20,9 @@ namespace mock
{
Session::Session(const char* zUser,
const char* zHost)
: m_client_dcb(this, zUser, zHost)
const char* zHost,
Dcb::Handler* pHandler)
: m_client_dcb(this, zUser, zHost, pHandler)
{
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)
{
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
{

View File

@ -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<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());
mock::Upstream upstream;
upstream.set_as_upstream_on(*sFilter_session.get());
rv += test(*sFilter_session.get(), router_session, c);