Commit d990b85f authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

introduced an abstract base Session class to allow tests to define and use a mock session class.

completed one notify test case using a mock session.  it identified a bug in the main code so the test fails right now.


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac221@2327 e5f2f494-b856-4b98-b285-d166d9295462
parent e121e2ed
......@@ -55,6 +55,7 @@
using namespace std;
using namespace isc;
using namespace isc::cc;
using namespace isc::datasrc;
using namespace isc::dns;
using namespace isc::dns::rdata;
......@@ -69,7 +70,8 @@ private:
AuthSrvImpl(const AuthSrvImpl& source);
AuthSrvImpl& operator=(const AuthSrvImpl& source);
public:
AuthSrvImpl(AbstractXfroutClient& xfrout_client);
AuthSrvImpl(AbstractSession& session_with_xfrin,
AbstractXfroutClient& xfrout_client);
~AuthSrvImpl();
isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
......@@ -90,7 +92,7 @@ public:
bool verbose_mode_;
bool is_notify_session_established_;
isc::cc::Session session_with_xfrin_;
AbstractSession& session_with_xfrin_;
bool is_axfr_connection_established_;
AbstractXfroutClient& xfrout_client_;
......@@ -99,9 +101,11 @@ public:
static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
};
AuthSrvImpl::AuthSrvImpl(AbstractXfroutClient& xfrout_client) :
AuthSrvImpl::AuthSrvImpl(AbstractSession& session_with_xfrin,
AbstractXfroutClient& xfrout_client) :
cs_(NULL), verbose_mode_(false),
is_notify_session_established_(false),
session_with_xfrin_(session_with_xfrin),
is_axfr_connection_established_(false),
xfrout_client_(xfrout_client)
{
......@@ -125,8 +129,9 @@ AuthSrvImpl::~AuthSrvImpl() {
}
}
AuthSrv::AuthSrv(AbstractXfroutClient& xfrout_client) :
impl_(new AuthSrvImpl(xfrout_client))
AuthSrv::AuthSrv(AbstractSession& session_with_xfrin,
AbstractXfroutClient& xfrout_client) :
impl_(new AuthSrvImpl(session_with_xfrin, xfrout_client))
{}
AuthSrv::~AuthSrv() {
......@@ -218,7 +223,8 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
// Ignore all responses.
if (message.getHeaderFlag(MessageFlag::QR())) {
if (impl_->verbose_mode_) {
cerr << "[b10-auth] received unexpected response, ignoring" << endl;
cerr << "[b10-auth] received unexpected response, ignoring"
<< endl;
}
return (false);
}
......@@ -231,8 +237,8 @@ AuthSrv::processMessage(const IOMessage& io_message, Message& message,
message.fromWire(request_buffer);
} catch (const DNSProtocolError& error) {
if (impl_->verbose_mode_) {
cerr << "[b10-auth] returning " << error.getRcode().toText() << ": "
<< error.what() << endl;
cerr << "[b10-auth] returning " << error.getRcode().toText()
<< ": " << error.what() << endl;
}
makeErrorMessage(message, response_renderer, error.getRcode(),
impl_->verbose_mode_);
......@@ -375,7 +381,7 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
// zone
if (!is_notify_session_established_) {
try {
session_with_xfrin_.establish();
session_with_xfrin_.establish(NULL);
is_notify_session_established_ = true;
} catch (const isc::cc::SessionError& err) {
if (verbose_mode_) {
......@@ -398,17 +404,18 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
try {
ElementPtr notify_command = Element::createFromString(
command_template_start + question->getName().toText() +
command_template_mid + remote_ip_address + command_template_end);
command_template_mid + remote_ip_address +
command_template_end);
const unsigned int seq =
session_with_xfrin_.group_sendmsg(notify_command, "Xfrin");
session_with_xfrin_.group_sendmsg(notify_command, "Xfrin",
"*", "*");
ElementPtr env, answer;
session_with_xfrin_.group_recvmsg(env, answer, false, seq);
int rcode;
parseAnswer(rcode, answer);
} catch (const isc::data::ParseError &err) {
if (verbose_mode_) {
cerr << "create notfiy command failed: "
<< err.what() << endl;
cerr << "create notfiy command failed: " << err.what() << endl;
}
return (false);
} catch (const isc::Exception& err) {
......
......@@ -51,7 +51,8 @@ private:
AuthSrv(const AuthSrv& source);
AuthSrv& operator=(const AuthSrv& source);
public:
explicit AuthSrv(isc::xfr::AbstractXfroutClient& xfrout_client);
AuthSrv(isc::cc::AbstractSession& session_with_xfrin,
isc::xfr::AbstractXfroutClient& xfrout_client);
~AuthSrv();
//@}
/// \return \c true if the \message contains a response to be returned;
......
......@@ -137,6 +137,7 @@ main(int argc, char* argv[]) {
// initialize command channel
int ret = 0;
Session session_with_xfrin;
XfroutClient xfrout_client(UNIX_SOCKET_FILE);
try {
string specfile;
......@@ -147,7 +148,7 @@ main(int argc, char* argv[]) {
specfile = string(AUTH_SPECFILE_LOCATION);
}
auth_server = new AuthSrv(xfrout_client);
auth_server = new AuthSrv(session_with_xfrin, xfrout_client);
auth_server->setVerbose(verbose_mode);
io_service = new asio_link::IOService(auth_server, port, use_ipv4,
......
......@@ -26,6 +26,7 @@
#include <dns/rrtype.h>
#include <cc/data.h>
#include <cc/session.h>
#include <xfr/xfrout_client.h>
......@@ -36,6 +37,7 @@
using isc::UnitTestUtil;
using namespace std;
using namespace isc::cc;
using namespace isc::dns;
using namespace isc::data;
using namespace isc::xfr;
......@@ -72,8 +74,27 @@ private:
bool send_ok_;
bool disconnect_ok_;
};
class MockSession : public AbstractSession {
public:
MockSession() :
// by default we return a simple "success" message.
msg_(Element::createFromString("{\"result\": [0, \"SUCCESS\"]}"))
{}
virtual void establish(const char* socket_file);
virtual void disconnect();
virtual int group_sendmsg(ElementPtr msg, string group,
string instance, string to);
virtual bool group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
bool nonblock, int seq);
void setMessage(ElementPtr msg) { msg_ = msg; }
private:
ElementPtr msg_;
};
protected:
AuthSrvTest() : server(xfrout), request_message(Message::RENDER),
AuthSrvTest() : server(notify_session, xfrout),
request_message(Message::RENDER),
parse_message(Message::PARSE), default_qid(0x1035),
opcode(Opcode(Opcode::QUERY())), qname("www.example.com"),
qclass(RRClass::IN()), qtype(RRType::A()),
......@@ -85,6 +106,7 @@ protected:
delete io_message;
delete endpoint;
}
MockSession notify_session;
MockXfroutClient xfrout;
AuthSrv server;
Message request_message;
......@@ -108,6 +130,33 @@ protected:
int protocol);
};
void
AuthSrvTest::MockSession::establish(const char* socket_file UNUSED_PARAM) {
}
void
AuthSrvTest::MockSession::disconnect() {
}
int
AuthSrvTest::MockSession::group_sendmsg(ElementPtr msg UNUSED_PARAM,
string group UNUSED_PARAM,
string instance UNUSED_PARAM,
string to UNUSED_PARAM)
{
return (0);
}
bool
AuthSrvTest::MockSession::group_recvmsg(ElementPtr& envelope UNUSED_PARAM,
ElementPtr& msg,
bool nonblock UNUSED_PARAM,
int seq UNUSED_PARAM)
{
msg = msg_;
return (true);
}
void
AuthSrvTest::MockXfroutClient::connect() {
if (!connect_ok_) {
......@@ -137,6 +186,7 @@ AuthSrvTest::MockXfroutClient::sendXfroutRequestInfo(
return (0);
}
// These are flags to indicate whether the corresponding flag bit of the
// DNS header is to be set in the test cases. (Note that the flag values
// is irrelevant to their wire-format values)
......@@ -402,8 +452,10 @@ TEST_F(AuthSrvTest, AXFRDisconnectFail) {
TEST_F(AuthSrvTest, notifyInTest) {
createRequest(Opcode::NOTIFY(), Name("example.com"), RRClass::IN(),
RRType::SOA());
EXPECT_EQ(false, server.processMessage(*io_message, parse_message,
EXPECT_EQ(true, server.processMessage(*io_message, parse_message,
response_renderer));
headerCheck(parse_message, default_qid, Rcode::NOERROR(),
Opcode::NOTIFY().getCode(), QR_FLAG | AA_FLAG, 1, 0, 0, 0);
}
void
......
......@@ -40,7 +40,43 @@ namespace isc {
isc::Exception(file, line, what) {}
};
class Session {
/// \brief The AbstractSession class is an abstract base class that
/// defines the interfaces of Session.
/// The intended primary usage of abstraction is to allow tests for the
/// user class of Session without requiring actual communication
/// channels.
/// For simplicity we only define the methods that are necessary for
/// existing test cases that use this base class. Eventually we'll
/// probably have to extend them.
class AbstractSession {
///
/// \name Constructors, Assignment Operator and Destructor.
///
/// Note: The copy constructor and the assignment operator are
/// intentionally defined as private to make it explicit that
/// this is a pure base class.
//@{
private:
AbstractSession(const AbstractSession& source);
AbstractSession& operator=(const AbstractSession& source);
protected:
AbstractSession() {}
public:
virtual ~AbstractSession() {}
//@}
virtual void establish(const char* socket_file) = 0;
virtual void disconnect() = 0;
virtual int group_sendmsg(isc::data::ElementPtr msg,
std::string group,
std::string instance,
std::string to) = 0;
virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
isc::data::ElementPtr& msg,
bool nonblock,
int seq) = 0;
};
class Session : public AbstractSession {
private:
SessionImpl* impl_;
......@@ -51,14 +87,14 @@ namespace isc {
public:
Session();
Session(asio::io_service& ioservice);
~Session();
virtual ~Session();
// XXX: quick hack to allow the user to watch the socket directly.
int getSocket() const;
void startRead(boost::function<void()> read_callback);
void establish(const char* socket_file = NULL);
virtual void establish(const char* socket_file = NULL);
void disconnect();
void sendmsg(isc::data::ElementPtr& msg);
void sendmsg(isc::data::ElementPtr& env,
......@@ -74,14 +110,14 @@ namespace isc {
std::string instance = "*");
void unsubscribe(std::string group,
std::string instance = "*");
int group_sendmsg(isc::data::ElementPtr msg,
std::string group,
std::string instance = "*",
std::string to = "*");
bool group_recvmsg(isc::data::ElementPtr& envelope,
isc::data::ElementPtr& msg,
bool nonblock = true,
int seq = -1);
virtual int group_sendmsg(isc::data::ElementPtr msg,
std::string group,
std::string instance = "*",
std::string to = "*");
virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
isc::data::ElementPtr& msg,
bool nonblock = true,
int seq = -1);
int reply(isc::data::ElementPtr& envelope,
isc::data::ElementPtr& newmsg);
bool hasQueuedMsgs();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment