Browse Source

introduced an abstract base Session class so that we can easily create test cases using a mock sessio implementation.

This is probably beyond the scope of this ticket, so it's probably better to make a separate ticket focusing on this refactoring.

Some tests currently fail.  They'll be fixed in the next commit.


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac221@2393 e5f2f494-b856-4b98-b285-d166d9295462
JINMEI Tatuya 15 years ago
parent
commit
ee4099c30d

+ 17 - 27
src/bin/auth/auth_srv.cc

@@ -70,8 +70,7 @@ private:
     AuthSrvImpl(const AuthSrvImpl& source);
     AuthSrvImpl(const AuthSrvImpl& source);
     AuthSrvImpl& operator=(const AuthSrvImpl& source);
     AuthSrvImpl& operator=(const AuthSrvImpl& source);
 public:
 public:
-    AuthSrvImpl(AbstractSession& session_with_xfrin,
-                AbstractXfroutClient& xfrout_client);
+    AuthSrvImpl(AbstractXfroutClient& xfrout_client);
     ~AuthSrvImpl();
     ~AuthSrvImpl();
     isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
     isc::data::ElementPtr setDbFile(const isc::data::ElementPtr config);
 
 
@@ -91,8 +90,7 @@ public:
 
 
     bool verbose_mode_;
     bool verbose_mode_;
 
 
-    bool is_notify_session_established_;
-    AbstractSession& session_with_xfrin_;
+    AbstractSession* session_with_xfrin_;
 
 
     bool is_axfr_connection_established_;
     bool is_axfr_connection_established_;
     AbstractXfroutClient& xfrout_client_;
     AbstractXfroutClient& xfrout_client_;
@@ -101,11 +99,9 @@ public:
     static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
     static const uint16_t DEFAULT_LOCAL_UDPSIZE = 4096;
 };
 };
 
 
-AuthSrvImpl::AuthSrvImpl(AbstractSession& session_with_xfrin,
-                         AbstractXfroutClient& xfrout_client) :
+AuthSrvImpl::AuthSrvImpl(AbstractXfroutClient& xfrout_client) :
     cs_(NULL), verbose_mode_(false),
     cs_(NULL), verbose_mode_(false),
-    is_notify_session_established_(false),
-    session_with_xfrin_(session_with_xfrin),
+    session_with_xfrin_(NULL),
     is_axfr_connection_established_(false),
     is_axfr_connection_established_(false),
     xfrout_client_(xfrout_client)
     xfrout_client_(xfrout_client)
 {
 {
@@ -118,20 +114,14 @@ AuthSrvImpl::AuthSrvImpl(AbstractSession& session_with_xfrin,
 }
 }
 
 
 AuthSrvImpl::~AuthSrvImpl() {
 AuthSrvImpl::~AuthSrvImpl() {
-    if (is_notify_session_established_) {
-        session_with_xfrin_.disconnect();
-        is_notify_session_established_ = false;
-    }
-
     if (is_axfr_connection_established_) {
     if (is_axfr_connection_established_) {
         xfrout_client_.disconnect();
         xfrout_client_.disconnect();
         is_axfr_connection_established_ = false;
         is_axfr_connection_established_ = false;
     }
     }
 }
 }
 
 
-AuthSrv::AuthSrv(AbstractSession& session_with_xfrin,
-                 AbstractXfroutClient& xfrout_client) :
-    impl_(new AuthSrvImpl(session_with_xfrin, xfrout_client))
+AuthSrv::AuthSrv(AbstractXfroutClient& xfrout_client) :
+    impl_(new AuthSrvImpl(xfrout_client))
 {}
 {}
 
 
 AuthSrv::~AuthSrv() {
 AuthSrv::~AuthSrv() {
@@ -201,6 +191,11 @@ AuthSrv::getVerbose() const {
 }
 }
 
 
 void
 void
+AuthSrv::setSession(AbstractSession* session) {
+    impl_->session_with_xfrin_ = session;
+}
+
+void
 AuthSrv::setConfigSession(ModuleCCSession* cs) {
 AuthSrv::setConfigSession(ModuleCCSession* cs) {
     impl_->cs_ = cs;
     impl_->cs_ = cs;
 }
 }
@@ -411,19 +406,14 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
     // error happens rather than returning (e.g.) SERVFAIL.  RFC 1996 is
     // error happens rather than returning (e.g.) SERVFAIL.  RFC 1996 is
     // silent about such cases, but there doesn't seem to be anything we can
     // silent about such cases, but there doesn't seem to be anything we can
     // improve at the primary server side by sending an error anyway.
     // improve at the primary server side by sending an error anyway.
-    if (!is_notify_session_established_) {
-        try {
-            session_with_xfrin_.establish(NULL);
-            is_notify_session_established_ = true;
-        } catch (const isc::cc::SessionError& err) {
+    if (session_with_xfrin_ == NULL) {
             if (verbose_mode_) {
             if (verbose_mode_) {
-                cerr << "[b10-auth] Error in connection with xfrin module: "
-                     << err.what() << endl;
+                cerr << "[b10-auth] "
+                    "session interface for xfrin is not available" << endl;
             }
             }
             return (false);
             return (false);
-        }
     }
     }
-    
+
     const string remote_ip_address =
     const string remote_ip_address =
         io_message.getRemoteEndpoint().getAddress().toText();
         io_message.getRemoteEndpoint().getAddress().toText();
     static const string command_template_start =
     static const string command_template_start =
@@ -437,10 +427,10 @@ AuthSrvImpl::processNotify(const IOMessage& io_message, Message& message,
                 command_template_mid + remote_ip_address +
                 command_template_mid + remote_ip_address +
                 command_template_end);
                 command_template_end);
         const unsigned int seq =
         const unsigned int seq =
-            session_with_xfrin_.group_sendmsg(notify_command, "Xfrin",
+            session_with_xfrin_->group_sendmsg(notify_command, "Xfrin",
                                               "*", "*");
                                               "*", "*");
         ElementPtr env, answer, parsed_answer;
         ElementPtr env, answer, parsed_answer;
-        session_with_xfrin_.group_recvmsg(env, answer, false, seq);
+        session_with_xfrin_->group_recvmsg(env, answer, false, seq);
         int rcode;
         int rcode;
         parsed_answer = parseAnswer(rcode, answer);
         parsed_answer = parseAnswer(rcode, answer);
         if (rcode != 0) {
         if (rcode != 0) {

+ 2 - 2
src/bin/auth/auth_srv.h

@@ -51,8 +51,7 @@ private:
     AuthSrv(const AuthSrv& source);
     AuthSrv(const AuthSrv& source);
     AuthSrv& operator=(const AuthSrv& source);
     AuthSrv& operator=(const AuthSrv& source);
 public:
 public:
-    AuthSrv(isc::cc::AbstractSession& session_with_xfrin,
-            isc::xfr::AbstractXfroutClient& xfrout_client);
+    AuthSrv(isc::xfr::AbstractXfroutClient& xfrout_client);
     ~AuthSrv();
     ~AuthSrv();
     //@}
     //@}
     /// \return \c true if the \message contains a response to be returned;
     /// \return \c true if the \message contains a response to be returned;
@@ -64,6 +63,7 @@ public:
     bool getVerbose() const;
     bool getVerbose() const;
     void serve(std::string zone_name);
     void serve(std::string zone_name);
     isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
     isc::data::ElementPtr updateConfig(isc::data::ElementPtr config);
+    void setSession(isc::cc::AbstractSession* session);
     isc::config::ModuleCCSession* configSession() const;
     isc::config::ModuleCCSession* configSession() const;
     void setConfigSession(isc::config::ModuleCCSession* cs);
     void setConfigSession(isc::config::ModuleCCSession* cs);
 private:
 private:

+ 23 - 10
src/bin/auth/main.cc

@@ -134,10 +134,10 @@ main(int argc, char* argv[]) {
         usage();
         usage();
     }
     }
 
 
-    // initialize command channel
     int ret = 0;
     int ret = 0;
 
 
-    Session session_with_xfrin; // we should eventually pass io_service here.
+    Session* cc_session = NULL;
+    ModuleCCSession* cs = NULL;
     XfroutClient xfrout_client(UNIX_SOCKET_FILE);
     XfroutClient xfrout_client(UNIX_SOCKET_FILE);
     try {
     try {
         string specfile;
         string specfile;
@@ -148,26 +148,39 @@ main(int argc, char* argv[]) {
             specfile = string(AUTH_SPECFILE_LOCATION);
             specfile = string(AUTH_SPECFILE_LOCATION);
         }
         }
 
 
-        auth_server = new AuthSrv(session_with_xfrin, xfrout_client);
+        auth_server = new AuthSrv(xfrout_client);
         auth_server->setVerbose(verbose_mode);
         auth_server->setVerbose(verbose_mode);
+        cout << "[b10-auth] Server created." << endl;
 
 
         io_service = new asio_link::IOService(auth_server, port, use_ipv4,
         io_service = new asio_link::IOService(auth_server, port, use_ipv4,
                                               use_ipv6);
                                               use_ipv6);
-
-        ModuleCCSession cs(specfile, io_service->get_io_service(),
-                           my_config_handler, my_command_handler);
-
-        auth_server->setConfigSession(&cs);
+        cout << "[b10-auth] IOService created." << endl;
+
+        cc_session = new Session(io_service->get_io_service());
+        cout << "[b10-auth] Session channel created." << endl;
+
+        cs = new ModuleCCSession(specfile, *cc_session, my_config_handler,
+                                 my_command_handler);
+        cout << "[b10-auth] Configuration channel established." << endl;
+
+        // XXX: with the current interface to asio_link we have to create
+        // auth_server before io_service while Session needs io_service.
+        // In a next step of refactoring we should make asio_link independent
+        // from auth_server, and create io_service, auth_server, and
+        // cc_session in that order.
+        auth_server->setSession(cc_session);
+        auth_server->setConfigSession(cs);
         auth_server->updateConfig(ElementPtr());
         auth_server->updateConfig(ElementPtr());
 
 
-        
         cout << "[b10-auth] Server started." << endl;
         cout << "[b10-auth] Server started." << endl;
         io_service->run();
         io_service->run();
     } catch (const std::exception& ex) {
     } catch (const std::exception& ex) {
-        cerr << "[b10-auth] " << ex.what() << endl;
+        cerr << "[b10-auth] Initialization failed: " << ex.what() << endl;
         ret = 1;
         ret = 1;
     }
     }
 
 
+    delete cs;
+    delete cc_session;
     delete io_service;
     delete io_service;
     delete auth_server;
     delete auth_server;
     return (ret);
     return (ret);

+ 20 - 2
src/bin/auth/tests/auth_srv_unittest.cc

@@ -16,6 +16,8 @@
 
 
 #include <config.h>
 #include <config.h>
 
 
+#include <boost/function.hpp>
+
 #include <gtest/gtest.h>
 #include <gtest/gtest.h>
 
 
 #include <dns/buffer.h>
 #include <dns/buffer.h>
@@ -89,6 +91,20 @@ private:
                                   string instance, string to);
                                   string instance, string to);
         virtual bool group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
         virtual bool group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
                                    bool nonblock, int seq);
                                    bool nonblock, int seq);
+        virtual void subscribe(string group UNUSED_PARAM,
+                               string instance UNUSED_PARAM)
+        {}
+        virtual void unsubscribe(string group UNUSED_PARAM,
+                                 string instance UNUSED_PARAM)
+        {}
+        virtual void startRead(
+            boost::function<void()> read_callback UNUSED_PARAM)
+        {}
+        virtual int reply(ElementPtr& envelope UNUSED_PARAM,
+                          ElementPtr& newmsg UNUSED_PARAM)
+        { return (0); }
+        virtual bool hasQueuedMsgs() { return (false); }
+
         void setMessage(ElementPtr msg) { msg_ = msg; }
         void setMessage(ElementPtr msg) { msg_ = msg; }
         bool isEstablished() const { return (is_established_); }
         bool isEstablished() const { return (is_established_); }
         void disableEstablish() { establish_ok_ = false; }
         void disableEstablish() { establish_ok_ = false; }
@@ -103,7 +119,7 @@ private:
     };
     };
 
 
 protected:
 protected:
-    AuthSrvTest() : server(notify_session, xfrout),
+    AuthSrvTest() : server(xfrout),
                     request_message(Message::RENDER),
                     request_message(Message::RENDER),
                     parse_message(Message::PARSE), default_qid(0x1035),
                     parse_message(Message::PARSE), default_qid(0x1035),
                     opcode(Opcode(Opcode::QUERY())), qname("www.example.com"),
                     opcode(Opcode(Opcode::QUERY())), qname("www.example.com"),
@@ -111,7 +127,9 @@ protected:
                     io_message(NULL), endpoint(NULL), request_obuffer(0),
                     io_message(NULL), endpoint(NULL), request_obuffer(0),
                     request_renderer(request_obuffer),
                     request_renderer(request_obuffer),
                     response_obuffer(0), response_renderer(response_obuffer)
                     response_obuffer(0), response_renderer(response_obuffer)
-    {}
+    {
+        server.setSession(&notify_session);
+    }
     ~AuthSrvTest() {
     ~AuthSrvTest() {
         delete io_message;
         delete io_message;
         delete endpoint;
         delete endpoint;

+ 45 - 144
src/lib/cc/session.cc

@@ -15,7 +15,7 @@
 // $Id$
 // $Id$
 
 
 #include <config.h>
 #include <config.h>
-#include "session_config.h"
+#include <cc/session_config.h>
 
 
 #include <stdint.h>
 #include <stdint.h>
 
 
@@ -41,8 +41,8 @@
 
 
 #include <exceptions/exceptions.h>
 #include <exceptions/exceptions.h>
 
 
-#include "data.h"
-#include "session.h"
+#include <cc/data.h>
+#include <cc/session.h>
 
 
 using namespace std;
 using namespace std;
 using namespace isc::cc;
 using namespace isc::cc;
@@ -51,44 +51,26 @@ using namespace isc::data;
 // some of the asio names conflict with socket API system calls
 // some of the asio names conflict with socket API system calls
 // (e.g. write(2)) so we don't import the entire asio namespace.
 // (e.g. write(2)) so we don't import the entire asio namespace.
 using asio::io_service;
 using asio::io_service;
-using asio::ip::tcp;
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
 
 
 namespace isc {
 namespace isc {
 namespace cc {
 namespace cc {
-
 class SessionImpl {
 class SessionImpl {
 public:
 public:
-    SessionImpl() : sequence_(-1) { queue_ = Element::createFromString("[]"); }
-    virtual ~SessionImpl() {}
-    virtual void establish(const char& socket_file) = 0;
-    virtual int getSocket() = 0;
-    virtual void disconnect() = 0;
-    virtual void writeData(const void* data, size_t datalen) = 0;
-    virtual size_t readDataLength() = 0;
-    virtual void readData(void* data, size_t datalen) = 0;
-    virtual void startRead(boost::function<void()> user_handler) = 0;
-    
+    SessionImpl(io_service& io_service) :
+        sequence_(-1), queue_(Element::createFromString("[]")),
+        io_service_(io_service), socket_(io_service_), data_length_(0)
+    {}
+    void establish(const char& socket_file);
+    void disconnect();
+    void writeData(const void* data, size_t datalen);
+    size_t readDataLength();
+    void readData(void* data, size_t datalen);
+    void startRead(boost::function<void()> user_handler);
+
     int sequence_; // the next sequence number to use
     int sequence_; // the next sequence number to use
     std::string lname_;
     std::string lname_;
     ElementPtr queue_;
     ElementPtr queue_;
-};
 
 
-class ASIOSession : public SessionImpl {
-public:
-    ASIOSession(io_service& io_service) :
-        io_service_(io_service), socket_(io_service_), data_length_(0)
-    {}
-    virtual void establish(const char& socket_file);
-    virtual void disconnect();
-    virtual int getSocket() { return (socket_.native()); }
-    virtual void writeData(const void* data, size_t datalen);
-    virtual size_t readDataLength();
-    virtual void readData(void* data, size_t datalen);
-    virtual void startRead(boost::function<void()> user_handler);
 private:
 private:
     void internalRead(const asio::error_code& error,
     void internalRead(const asio::error_code& error,
                       size_t bytes_transferred);
                       size_t bytes_transferred);
@@ -101,28 +83,28 @@ private:
     asio::error_code error_;
     asio::error_code error_;
 };
 };
 
 
-
-
 void
 void
-ASIOSession::establish(const char& socket_file) {
+SessionImpl::establish(const char& socket_file) {
     try {
     try {
-        socket_.connect(asio::local::stream_protocol::endpoint(&socket_file), error_);
-    } catch (asio::system_error& se) {
+        socket_.connect(asio::local::stream_protocol::endpoint(&socket_file),
+                        error_);
+    } catch(const asio::system_error& se) {
         isc_throw(SessionError, se.what());
         isc_throw(SessionError, se.what());
     }
     }
     if (error_) {
     if (error_) {
-        isc_throw(SessionError, "Unable to connect to message queue.");
+        isc_throw(SessionError, "Unable to connect to message queue: " <<
+                  error_.message());
     }
     }
 }
 }
 
 
 void
 void
-ASIOSession::disconnect() {
+SessionImpl::disconnect() {
     socket_.close();
     socket_.close();
     data_length_ = 0;
     data_length_ = 0;
 }
 }
 
 
 void
 void
-ASIOSession::writeData(const void* data, size_t datalen) {
+SessionImpl::writeData(const void* data, size_t datalen) {
     try {
     try {
         asio::write(socket_, asio::buffer(data, datalen));
         asio::write(socket_, asio::buffer(data, datalen));
     } catch (const asio::system_error& asio_ex) {
     } catch (const asio::system_error& asio_ex) {
@@ -131,7 +113,7 @@ ASIOSession::writeData(const void* data, size_t datalen) {
 }
 }
 
 
 size_t
 size_t
-ASIOSession::readDataLength() {
+SessionImpl::readDataLength() {
     size_t ret_len = data_length_;
     size_t ret_len = data_length_;
     
     
     if (ret_len == 0) {
     if (ret_len == 0) {
@@ -147,7 +129,7 @@ ASIOSession::readDataLength() {
 }
 }
 
 
 void
 void
-ASIOSession::readData(void* data, size_t datalen) {
+SessionImpl::readData(void* data, size_t datalen) {
     try {
     try {
         asio::read(socket_, asio::buffer(data, datalen));
         asio::read(socket_, asio::buffer(data, datalen));
     } catch (const asio::system_error& asio_ex) {
     } catch (const asio::system_error& asio_ex) {
@@ -158,18 +140,18 @@ ASIOSession::readData(void* data, size_t datalen) {
 }
 }
 
 
 void
 void
-ASIOSession::startRead(boost::function<void()> user_handler) {
+SessionImpl::startRead(boost::function<void()> user_handler) {
     data_length_ = 0;
     data_length_ = 0;
     user_handler_ = user_handler;
     user_handler_ = user_handler;
     async_read(socket_, asio::buffer(&data_length_,
     async_read(socket_, asio::buffer(&data_length_,
                                             sizeof(data_length_)),
                                             sizeof(data_length_)),
-               boost::bind(&ASIOSession::internalRead, this,
+               boost::bind(&SessionImpl::internalRead, this,
                            asio::placeholders::error,
                            asio::placeholders::error,
                            asio::placeholders::bytes_transferred));
                            asio::placeholders::bytes_transferred));
 }
 }
 
 
 void
 void
-ASIOSession::internalRead(const asio::error_code& error,
+SessionImpl::internalRead(const asio::error_code& error,
                           size_t bytes_transferred)
                           size_t bytes_transferred)
 {
 {
     if (!error) {
     if (!error) {
@@ -184,27 +166,22 @@ ASIOSession::internalRead(const asio::error_code& error,
     }
     }
 }
 }
 
 
-class SocketSession : public SessionImpl {
-public:
-    SocketSession() : sock_(-1) {}
-    virtual ~SocketSession() { disconnect(); }
-    virtual int getSocket() { return (sock_); }
-    void establish(const char& socket_file);
-    virtual void disconnect()
-    {
-        if (sock_ >= 0) {
-            close(sock_);
-        }
-        sock_ = -1;
-    }
-    virtual void writeData(const void* data, size_t datalen);
-    virtual void readData(void* data, size_t datalen);
-    virtual size_t readDataLength();
-    virtual void startRead(boost::function<void()> user_handler UNUSED_PARAM)
-    {} // nothing to do for this class
-private:
-    int sock_;
-};
+Session::Session(io_service& io_service) : impl_(new SessionImpl(io_service))
+{}
+
+Session::~Session() {
+    delete impl_;
+}
+
+void
+Session::disconnect() {
+    impl_->disconnect();
+}
+
+void
+Session::startRead(boost::function<void()> read_callback) {
+    impl_->startRead(read_callback);
+}
 
 
 namespace {                     // maybe unnecessary.
 namespace {                     // maybe unnecessary.
 // This is a helper class to make the establish() method (below) exception-safe
 // This is a helper class to make the establish() method (below) exception-safe
@@ -224,83 +201,6 @@ public:
 }
 }
 
 
 void
 void
-SocketSession::establish(const char& socket_file) {
-    struct sockaddr_un s_un;
-#ifdef HAVE_SA_LEN
-    s_un.sun_len = sizeof(struct sockaddr_un);
-#endif
-
-    if (strlen(&socket_file) >= sizeof(s_un.sun_path)) {
-        isc_throw(SessionError, "Unable to connect to message queue; "
-                  "socket file path too long: " << socket_file);
-    }
-    s_un.sun_family = AF_UNIX;
-    strncpy(s_un.sun_path, &socket_file, sizeof(s_un.sun_path) - 1);
-
-    int s = socket(AF_UNIX, SOCK_STREAM, 0);
-    if (s < 0) {
-        isc_throw(SessionError, "socket() failed");
-    }
-
-    if (connect(s, (struct sockaddr *)&s_un, sizeof(s_un)) < 0) {
-        close(s);
-        isc_throw(SessionError, "Unable to connect to message queue");
-    }
-
-    sock_ = s;
-}
-
-void
-SocketSession::writeData(const void* data, const size_t datalen) {
-    int cc = write(sock_, data, datalen);
-    if (cc != datalen) {
-        isc_throw(SessionError, "Write failed: expect " << datalen <<
-                  ", actual " << cc);
-    }
-}
-
-size_t
-SocketSession::readDataLength() {
-    uint32_t length;
-    readData(&length, sizeof(length));
-    return (ntohl(length));
-}
-
-void
-SocketSession::readData(void* data, const size_t datalen) {
-    int cc = read(sock_, data, datalen);
-    if (cc != datalen) {
-        isc_throw(SessionError, "Read failed: expect " << datalen <<
-                  ", actual " << cc);
-    }
-}
-
-Session::Session() : impl_(new SocketSession)
-{}
-
-Session::Session(io_service& io_service) : impl_(new ASIOSession(io_service))
-{}
-
-Session::~Session() {
-    delete impl_;
-}
-
-void
-Session::disconnect() {
-    impl_->disconnect();
-}
-
-int
-Session::getSocket() const {
-    return (impl_->getSocket());
-}
-
-void
-Session::startRead(boost::function<void()> read_callback) {
-    impl_->startRead(read_callback);
-}
-
-void
 Session::establish(const char* socket_file) {
 Session::establish(const char* socket_file) {
     if (socket_file == NULL) {
     if (socket_file == NULL) {
         socket_file = getenv("BIND10_MSGQ_SOCKET_FILE");
         socket_file = getenv("BIND10_MSGQ_SOCKET_FILE");
@@ -333,7 +233,8 @@ Session::establish(const char* socket_file) {
 }
 }
 
 
 //
 //
-// Convert to wire format and send this on the TCP stream with its length prefix
+// Convert to wire format and send this via the stream socket with its length
+// prefix.
 //
 //
 void
 void
 Session::sendmsg(ElementPtr& msg) {
 Session::sendmsg(ElementPtr& msg) {

+ 19 - 15
src/lib/cc/session.h

@@ -68,12 +68,20 @@ namespace isc {
             virtual void disconnect() = 0;
             virtual void disconnect() = 0;
             virtual int group_sendmsg(isc::data::ElementPtr msg,
             virtual int group_sendmsg(isc::data::ElementPtr msg,
                                       std::string group,
                                       std::string group,
-                                      std::string instance,
-                                      std::string to) = 0;
+                                      std::string instance = "*",
+                                      std::string to = "*") = 0;
             virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
             virtual bool group_recvmsg(isc::data::ElementPtr& envelope,
                                        isc::data::ElementPtr& msg,
                                        isc::data::ElementPtr& msg,
-                                       bool nonblock,
-                                       int seq) = 0;
+                                       bool nonblock = true,
+                                       int seq = -1) = 0;
+            virtual void subscribe(std::string group,
+                                   std::string instance = "*") = 0;
+            virtual void unsubscribe(std::string group,
+                             std::string instance = "*") = 0;
+            virtual void startRead(boost::function<void()> read_callback) = 0;
+            virtual int reply(isc::data::ElementPtr& envelope,
+                               isc::data::ElementPtr& newmsg) = 0;
+            virtual bool hasQueuedMsgs() = 0;
         };
         };
 
 
     class Session : public AbstractSession {
     class Session : public AbstractSession {
@@ -85,14 +93,10 @@ namespace isc {
             Session& operator=(const Session& source);
             Session& operator=(const Session& source);
 
 
         public:
         public:
-            Session();
             Session(asio::io_service& ioservice);
             Session(asio::io_service& ioservice);
             virtual ~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);
+            virtual void startRead(boost::function<void()> read_callback);
 
 
             virtual void establish(const char* socket_file = NULL);
             virtual void establish(const char* socket_file = NULL);
             void disconnect();
             void disconnect();
@@ -106,9 +110,9 @@ namespace isc {
                          isc::data::ElementPtr& msg,
                          isc::data::ElementPtr& msg,
                          bool nonblock = true,
                          bool nonblock = true,
                          int seq = -1);
                          int seq = -1);
-            void subscribe(std::string group,
-                           std::string instance = "*");
-            void unsubscribe(std::string group,
+            virtual void subscribe(std::string group,
+                                   std::string instance = "*");
+            virtual void unsubscribe(std::string group,
                              std::string instance = "*");
                              std::string instance = "*");
             virtual int group_sendmsg(isc::data::ElementPtr msg,
             virtual int group_sendmsg(isc::data::ElementPtr msg,
                                       std::string group,
                                       std::string group,
@@ -118,9 +122,9 @@ namespace isc {
                                        isc::data::ElementPtr& msg,
                                        isc::data::ElementPtr& msg,
                                        bool nonblock = true,
                                        bool nonblock = true,
                                        int seq = -1);
                                        int seq = -1);
-            int reply(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& newmsg);
-            bool hasQueuedMsgs();
+            virtual int reply(isc::data::ElementPtr& envelope,
+                              isc::data::ElementPtr& newmsg);
+            virtual bool hasQueuedMsgs();
         };
         };
     } // namespace cc
     } // namespace cc
 } // namespace isc
 } // namespace isc

+ 0 - 19
src/lib/cc/session_unittests.cc

@@ -45,22 +45,3 @@ TEST(AsioSession, establish) {
     );
     );
                   
                   
 }
 }
-
-TEST(Session, establish) {
-    Session sess;
-
-    EXPECT_THROW(
-        sess.establish("/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                       "/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/aaaaaaaaaa/"
-                  ), isc::cc::SessionError
-    );
-                  
-}

+ 3 - 19
src/lib/config/ccsession.cc

@@ -198,12 +198,12 @@ ModuleCCSession::startCheck() {
 
 
 ModuleCCSession::ModuleCCSession(
 ModuleCCSession::ModuleCCSession(
     std::string spec_file_name,
     std::string spec_file_name,
-    asio::io_service& io_service,
+    isc::cc::AbstractSession& session,
     isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
     isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
     isc::data::ElementPtr(*command_handler)(
     isc::data::ElementPtr(*command_handler)(
         const std::string& command, const isc::data::ElementPtr args)
         const std::string& command, const isc::data::ElementPtr args)
     ) throw (isc::cc::SessionError) :
     ) throw (isc::cc::SessionError) :
-    session_(io_service)
+    session_(session)
 {
 {
     init(spec_file_name, config_handler, command_handler);
     init(spec_file_name, config_handler, command_handler);
 
 
@@ -211,16 +211,6 @@ ModuleCCSession::ModuleCCSession(
     session_.startRead(boost::bind(&ModuleCCSession::startCheck, this));
     session_.startRead(boost::bind(&ModuleCCSession::startCheck, this));
 }
 }
 
 
-ModuleCCSession::ModuleCCSession(
-    std::string spec_file_name,
-    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config),
-    isc::data::ElementPtr(*command_handler)(
-        const std::string& command, const isc::data::ElementPtr args)
-    ) throw (isc::cc::SessionError)
-{
-    init(spec_file_name, config_handler, command_handler);
-}
-
 void
 void
 ModuleCCSession::init(
 ModuleCCSession::init(
     std::string spec_file_name,
     std::string spec_file_name,
@@ -238,7 +228,7 @@ ModuleCCSession::init(
 
 
     ElementPtr answer, env;
     ElementPtr answer, env;
 
 
-    session_.establish();
+    session_.establish(NULL);
     session_.subscribe(module_name_, "*");
     session_.subscribe(module_name_, "*");
     //session_.subscribe("Boss", "*");
     //session_.subscribe("Boss", "*");
     //session_.subscribe("statistics", "*");
     //session_.subscribe("statistics", "*");
@@ -300,12 +290,6 @@ ModuleCCSession::handleConfigUpdate(ElementPtr new_config)
     return answer;
     return answer;
 }
 }
 
 
-int
-ModuleCCSession::getSocket()
-{
-    return (session_.getSocket());
-}
-
 bool
 bool
 ModuleCCSession::hasQueuedMsgs()
 ModuleCCSession::hasQueuedMsgs()
 {
 {

+ 7 - 23
src/lib/config/ccsession.h

@@ -24,10 +24,6 @@
 #include <cc/session.h>
 #include <cc/session.h>
 #include <cc/data.h>
 #include <cc/data.h>
 
 
-namespace asio {
-class io_service;
-}
-
 namespace isc {
 namespace isc {
 namespace config {
 namespace config {
 
 
@@ -127,27 +123,15 @@ public:
      *                        module specification.
      *                        module specification.
      */
      */
     ModuleCCSession(std::string spec_file_name,
     ModuleCCSession(std::string spec_file_name,
-                    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config) = NULL,
-                    isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args) = NULL
-                    ) throw (isc::cc::SessionError);
-    ModuleCCSession(std::string spec_file_name,
-                    asio::io_service& io_service,
-                    isc::data::ElementPtr(*config_handler)(isc::data::ElementPtr new_config) = NULL,
-                    isc::data::ElementPtr(*command_handler)(const std::string& command, const isc::data::ElementPtr args) = NULL
+                    isc::cc::AbstractSession& session,
+                    isc::data::ElementPtr(*config_handler)(
+                        isc::data::ElementPtr new_config) = NULL,
+                    isc::data::ElementPtr(*command_handler)(
+                        const std::string& command,
+                        const isc::data::ElementPtr args) = NULL
                     ) throw (isc::cc::SessionError);
                     ) throw (isc::cc::SessionError);
 
 
     /**
     /**
-     * Returns the socket that is used to communicate with the msgq
-     * command channel. This socket should *only* be used to run a
-     * select() loop over it. And if not time-critical, it is strongly
-     * recommended to only use checkCommand() to check for messages
-     *
-     * @return The socket used to communicate with the msgq command
-     *         channel.
-     */
-    int getSocket();
-
-    /**
      * Optional optimization for checkCommand loop; returns true
      * Optional optimization for checkCommand loop; returns true
      * if there are unhandled queued messages in the cc session.
      * if there are unhandled queued messages in the cc session.
      * (if either this is true or there is data on the socket found
      * (if either this is true or there is data on the socket found
@@ -238,7 +222,7 @@ private:
     void startCheck();
     void startCheck();
     
     
     std::string module_name_;
     std::string module_name_;
-    isc::cc::Session session_;
+    isc::cc::AbstractSession& session_;
     ModuleSpec module_specification_;
     ModuleSpec module_specification_;
     ElementPtr handleConfigUpdate(ElementPtr new_config);
     ElementPtr handleConfigUpdate(ElementPtr new_config);
 
 

File diff suppressed because it is too large
+ 111 - 130
src/lib/config/tests/ccsession_unittests.cc


+ 110 - 111
src/lib/config/tests/fake_session.cc

@@ -38,26 +38,21 @@ using namespace isc::data;
 #include <sys/socket.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netinet/in.h>
 
 
-isc::data::ElementPtr initial_messages;
-isc::data::ElementPtr subscriptions;
-isc::data::ElementPtr msg_queue;
-
 // ok i want these in cc/data 
 // ok i want these in cc/data 
-static bool
-listContains(ElementPtr list, ElementPtr el)
-{
+bool
+listContains(ElementPtr list, ElementPtr el) {
     if (!list) {
     if (!list) {
-        return false;
+        return (false);
     }
     }
     BOOST_FOREACH(ElementPtr l_el, list->listValue()) {
     BOOST_FOREACH(ElementPtr l_el, list->listValue()) {
         if (l_el == el) {
         if (l_el == el) {
-            return true;
+            return (true);
         }
         }
     }
     }
-    return false;
+    return (false);
 }
 }
 
 
-static void
+void
 listRemove(ElementPtr list, ElementPtr el) {
 listRemove(ElementPtr list, ElementPtr el) {
     int i = -1;
     int i = -1;
     BOOST_FOREACH(ElementPtr s_el, list->listValue()) {
     BOOST_FOREACH(ElementPtr s_el, list->listValue()) {
@@ -72,119 +67,65 @@ listRemove(ElementPtr list, ElementPtr el) {
 }
 }
 // endwant
 // endwant
 
 
-ElementPtr
-getFirstMessage(std::string& group, std::string& to)
-{
-    ElementPtr el;
-    if (msg_queue && msg_queue->size() > 0) {
-        el = msg_queue->get(0);
-        msg_queue->remove(0);
-        group = el->get(0)->stringValue();
-        to = el->get(1)->stringValue();
-        return el->get(2);
-    } else {
-        group = "";
-        to = "";
-        return ElementPtr();
-    }
-}
-
-void
-addMessage(ElementPtr msg, const std::string& group, const std::string& to)
-{
-    ElementPtr m_el = Element::createFromString("[]");
-    m_el->add(Element::create(group));
-    m_el->add(Element::create(to));
-    m_el->add(msg);
-    if (!msg_queue) {
-        msg_queue = Element::createFromString("[]");
-    }
-    msg_queue->add(m_el);
-}
-
-bool
-haveSubscription(const std::string& group, const std::string& instance)
-{
-    if (!subscriptions) {
-        return false;
-    }
-    ElementPtr s1 = Element::createFromString("[]");
-    ElementPtr s2 = Element::createFromString("[]");
-    s1->add(Element::create(group));
-    s1->add(Element::create(instance));
-    s2->add(Element::create(group));
-    s2->add(Element::create("*"));
-    bool result = (listContains(subscriptions, s1) || listContains(subscriptions, s2));
-    return result;
-}
-
-bool
-haveSubscription(const ElementPtr group, const ElementPtr instance)
-{
-    return haveSubscription(group->stringValue(), instance->stringValue());
-}
-
 namespace isc {
 namespace isc {
 namespace cc {
 namespace cc {
 
 
-Session::Session()
-{
-}
-
-Session::Session(asio::io_service& io_service UNUSED_PARAM)
+FakeSession::FakeSession(isc::data::ElementPtr initial_messages,
+                         isc::data::ElementPtr subscriptions,
+                         isc::data::ElementPtr msg_queue) :
+    messages_(initial_messages),
+    subscriptions_(subscriptions),
+    msg_queue_(msg_queue)
 {
 {
 }
 }
 
 
-Session::~Session() {
+FakeSession::~FakeSession() {
 }
 }
 
 
 bool
 bool
-Session::connect() {
-    return true;
+FakeSession::connect() {
+    return (true);
 }
 }
 
 
 void
 void
-Session::disconnect() {
-}
-
-int
-Session::getSocket() const {
-    return 1;
+FakeSession::disconnect() {
 }
 }
 
 
 void
 void
-Session::startRead(boost::function<void()> read_callback UNUSED_PARAM) {
+FakeSession::startRead(boost::function<void()> read_callback UNUSED_PARAM) {
 }
 }
 
 
 void
 void
-Session::establish(const char* socket_file) {
+FakeSession::establish(const char* socket_file) {
 }
 }
 
 
 //
 //
 // Convert to wire format and send this on the TCP stream with its length prefix
 // Convert to wire format and send this on the TCP stream with its length prefix
 //
 //
 void
 void
-Session::sendmsg(ElementPtr& msg) {
+FakeSession::sendmsg(ElementPtr& msg) {
     //cout << "[XX] client sends message: " << msg << endl;
     //cout << "[XX] client sends message: " << msg << endl;
     // err, to where?
     // err, to where?
     addMessage(msg, "*", "*");
     addMessage(msg, "*", "*");
 }
 }
 
 
 void
 void
-Session::sendmsg(ElementPtr& env, ElementPtr& msg) {
+FakeSession::sendmsg(ElementPtr& env, ElementPtr& msg) {
     //cout << "[XX] client sends message: " << msg << endl;
     //cout << "[XX] client sends message: " << msg << endl;
     //cout << "[XX] env: " << env << endl;
     //cout << "[XX] env: " << env << endl;
     addMessage(msg, env->get("group")->stringValue(), env->get("to")->stringValue());
     addMessage(msg, env->get("group")->stringValue(), env->get("to")->stringValue());
 }
 }
 
 
 bool
 bool
-Session::recvmsg(ElementPtr& msg, bool nonblock UNUSED_PARAM, int seq UNUSED_PARAM) {
+FakeSession::recvmsg(ElementPtr& msg, bool nonblock UNUSED_PARAM,
+                     int seq UNUSED_PARAM)
+{
     //cout << "[XX] client asks for message " << endl;
     //cout << "[XX] client asks for message " << endl;
-    if (initial_messages &&
-        initial_messages->getType() == Element::list &&
-        initial_messages->size() > 0) {
-        msg = initial_messages->get(0);
-        initial_messages->remove(0);
+    if (messages_ &&
+        messages_->getType() == Element::list &&
+        messages_->size() > 0) {
+        msg = messages_->get(0);
+        messages_->remove(0);
     } else {
     } else {
         msg = ElementPtr();
         msg = ElementPtr();
     }
     }
@@ -192,18 +133,21 @@ Session::recvmsg(ElementPtr& msg, bool nonblock UNUSED_PARAM, int seq UNUSED_PAR
 }
 }
 
 
 bool
 bool
-Session::recvmsg(ElementPtr& env, ElementPtr& msg, bool nonblock UNUSED_PARAM, int seq UNUSED_PARAM) {
+FakeSession::recvmsg(ElementPtr& env, ElementPtr& msg,
+                     bool nonblock UNUSED_PARAM,
+                     int seq UNUSED_PARAM)
+{
     //cout << "[XX] client asks for message and env" << endl;
     //cout << "[XX] client asks for message and env" << endl;
     env = ElementPtr();
     env = ElementPtr();
-    if (initial_messages &&
-        initial_messages->getType() == Element::list &&
-        initial_messages->size() > 0) {
+    if (messages_ &&
+        messages_->getType() == Element::list &&
+        messages_->size() > 0) {
         // do we need initial message to have env[group] and [to] too?
         // do we need initial message to have env[group] and [to] too?
-        msg = initial_messages->get(0);
-        initial_messages->remove(0);
+        msg = messages_->get(0);
+        messages_->remove(0);
         return true;
         return true;
-    } else if (msg_queue) {
-        BOOST_FOREACH(ElementPtr c_m, msg_queue->listValue()) {
+    } else if (msg_queue_) {
+        BOOST_FOREACH(ElementPtr c_m, msg_queue_->listValue()) {
             ElementPtr to_remove = ElementPtr();
             ElementPtr to_remove = ElementPtr();
             if (haveSubscription(c_m->get(0), c_m->get(1))) {
             if (haveSubscription(c_m->get(0), c_m->get(1))) {
                 env = Element::createFromString("{}");
                 env = Element::createFromString("{}");
@@ -213,7 +157,7 @@ Session::recvmsg(ElementPtr& env, ElementPtr& msg, bool nonblock UNUSED_PARAM, i
                 to_remove = c_m;
                 to_remove = c_m;
             }
             }
             if (to_remove) {
             if (to_remove) {
-                listRemove(msg_queue, to_remove);
+                listRemove(msg_queue_, to_remove);
                 return true;
                 return true;
             }
             }
         }
         }
@@ -224,32 +168,32 @@ Session::recvmsg(ElementPtr& env, ElementPtr& msg, bool nonblock UNUSED_PARAM, i
 }
 }
 
 
 void
 void
-Session::subscribe(std::string group, std::string instance) {
+FakeSession::subscribe(std::string group, std::string instance) {
     //cout << "[XX] client subscribes to " << group << " . " << instance << endl;
     //cout << "[XX] client subscribes to " << group << " . " << instance << endl;
     ElementPtr s_el = Element::createFromString("[]");
     ElementPtr s_el = Element::createFromString("[]");
     s_el->add(Element::create(group));
     s_el->add(Element::create(group));
     s_el->add(Element::create(instance));
     s_el->add(Element::create(instance));
-    if (!subscriptions) {
-        subscriptions = Element::createFromString("[]");
+    if (!subscriptions_) {
+        subscriptions_ = Element::createFromString("[]");
     }
     }
-    subscriptions->add(s_el);
+    subscriptions_->add(s_el);
 }
 }
 
 
 void
 void
-Session::unsubscribe(std::string group, std::string instance) {
+FakeSession::unsubscribe(std::string group, std::string instance) {
     //cout << "[XX] client unsubscribes from " << group << " . " << instance << endl;
     //cout << "[XX] client unsubscribes from " << group << " . " << instance << endl;
     ElementPtr s_el = Element::createFromString("[]");
     ElementPtr s_el = Element::createFromString("[]");
     s_el->add(Element::create(group));
     s_el->add(Element::create(group));
     s_el->add(Element::create(instance));
     s_el->add(Element::create(instance));
-    if (!subscriptions) {
+    if (!subscriptions_) {
         return;
         return;
     }
     }
-    listRemove(subscriptions, s_el);
+    listRemove(subscriptions_, s_el);
 }
 }
 
 
-unsigned int
-Session::group_sendmsg(ElementPtr msg, std::string group,
-                       std::string to, std::string instance UNUSED_PARAM)
+int
+FakeSession::group_sendmsg(ElementPtr msg, std::string group,
+                           std::string to, std::string instance UNUSED_PARAM)
 {
 {
     //cout << "[XX] client sends message: " << msg << endl;
     //cout << "[XX] client sends message: " << msg << endl;
     //cout << "[XX] to: " << group << " . " << instance << "." << to << endl;
     //cout << "[XX] to: " << group << " . " << instance << "." << to << endl;
@@ -258,14 +202,14 @@ Session::group_sendmsg(ElementPtr msg, std::string group,
 }
 }
 
 
 bool
 bool
-Session::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
-                       bool nonblock, int seq)
+FakeSession::group_recvmsg(ElementPtr& envelope, ElementPtr& msg,
+                           bool nonblock, int seq)
 {
 {
     return (recvmsg(envelope, msg, nonblock, seq));
     return (recvmsg(envelope, msg, nonblock, seq));
 }
 }
 
 
-unsigned int
-Session::reply(ElementPtr& envelope, ElementPtr& newmsg) {
+int
+FakeSession::reply(ElementPtr& envelope, ElementPtr& newmsg) {
     //cout << "[XX] client sends reply: " << newmsg << endl;
     //cout << "[XX] client sends reply: " << newmsg << endl;
     //cout << "[XX] env: " << envelope << endl;
     //cout << "[XX] env: " << envelope << endl;
     addMessage(newmsg, envelope->get("group")->stringValue(), envelope->get("to")->stringValue());
     addMessage(newmsg, envelope->get("group")->stringValue(), envelope->get("to")->stringValue());
@@ -273,9 +217,64 @@ Session::reply(ElementPtr& envelope, ElementPtr& newmsg) {
 }
 }
 
 
 bool
 bool
-Session::hasQueuedMsgs() {
+FakeSession::hasQueuedMsgs() {
     return false;
     return false;
 }
 }
 
 
+ElementPtr
+FakeSession::getFirstMessage(std::string& group, std::string& to) {
+    ElementPtr el;
+    if (msg_queue_ && msg_queue_->size() > 0) {
+        el = msg_queue_->get(0);
+        msg_queue_->remove(0);
+        group = el->get(0)->stringValue();
+        to = el->get(1)->stringValue();
+        return el->get(2);
+    } else {
+        group = "";
+        to = "";
+        return (ElementPtr());
+    }
+}
+
+void
+FakeSession::addMessage(ElementPtr msg, const std::string& group,
+                        const std::string& to)
+{
+    ElementPtr m_el = Element::createFromString("[]");
+    m_el->add(Element::create(group));
+    m_el->add(Element::create(to));
+    m_el->add(msg);
+    if (!msg_queue_) {
+        msg_queue_ = Element::createFromString("[]");
+    }
+    msg_queue_->add(m_el);
+}
+
+bool
+FakeSession::haveSubscription(const std::string& group,
+                              const std::string& instance)
+{
+    if (!subscriptions_) {
+        return (false);
+    }
+    ElementPtr s1 = Element::createFromString("[]");
+    ElementPtr s2 = Element::createFromString("[]");
+    s1->add(Element::create(group));
+    s1->add(Element::create(instance));
+    s2->add(Element::create(group));
+    s2->add(Element::create("*"));
+    bool result = (listContains(subscriptions_, s1) ||
+                   listContains(subscriptions_, s2));
+    return (result);
+}
+
+bool
+FakeSession::haveSubscription(const ElementPtr group,
+                              const ElementPtr instance)
+{
+    return (haveSubscription(group->stringValue(), instance->stringValue()));
+}
+
 }
 }
 }
 }

+ 65 - 72
src/lib/config/tests/fake_session.h

@@ -14,8 +14,8 @@
 
 
 // $Id: session.h 1250 2010-03-09 22:52:15Z jinmei $
 // $Id: session.h 1250 2010-03-09 22:52:15Z jinmei $
 
 
-#ifndef _ISC_SESSION_H
-#define _ISC_SESSION_H 1
+#ifndef _ISC_FAKESESSION_H
+#define _ISC_FAKESESSION_H 1
 
 
 #include <string>
 #include <string>
 
 
@@ -24,85 +24,78 @@
 #include <exceptions/exceptions.h>
 #include <exceptions/exceptions.h>
 
 
 #include <cc/data.h>
 #include <cc/data.h>
-
-namespace asio {
-class io_service;
-}
-
-// global variables so tests can insert
-// update and check, before, during and after
-// the actual session object was created/destroyed
-
-// if initial_messages contains a list of messages,
-// these are sent when recv_msg or group_recvmsg is called
-// instead of whatever is in the msg queue
-extern isc::data::ElementPtr initial_messages;
-extern isc::data::ElementPtr subscriptions;
-extern isc::data::ElementPtr msg_queue;
-
-bool haveSubscription(const std::string& group, const std::string& instance);
-bool haveSubscription(const isc::data::ElementPtr group, const isc::data::ElementPtr instance);
-isc::data::ElementPtr getFirstMessage(std::string& group, std::string& to);
-void addMessage(isc::data::ElementPtr, const std::string& group, const std::string& to);
+#include <cc/session.h>
 
 
 namespace isc {
 namespace isc {
-    namespace cc {
-
-        class SessionError : public isc::Exception {
-        public:
-            SessionError(const char* file, size_t line, const char* what) :
-                isc::Exception(file, line, what) {}
-        };
-
-        class Session {
-        private:
-            Session(const Session& source);
-            Session& operator=(const Session& source);
-
-        public:
-            // public so tests can inspect them
-        
-            Session();
-            Session(asio::io_service& ioservice);
-            ~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);
-            bool connect();
-            void disconnect();
-            void sendmsg(isc::data::ElementPtr& msg);
-            void sendmsg(isc::data::ElementPtr& env,
-                         isc::data::ElementPtr& msg);
-            bool recvmsg(isc::data::ElementPtr& msg,
-                         bool nonblock = true, int seq = -1);
-            bool recvmsg(isc::data::ElementPtr& env,
-                         isc::data::ElementPtr& msg,
-                         bool nonblock = true, int seq = -1);
-            void subscribe(std::string group,
+namespace cc {
+class FakeSession : public AbstractSession {
+private:
+    FakeSession(const Session& source);
+    FakeSession& operator=(const Session& source);
+
+public:
+    // public so tests can inspect them
+
+    // if initial_messages contains a list of messages,
+    // these are sent when recv_msg or group_recvmsg is called
+    // instead of whatever is in the msg queue
+    FakeSession(isc::data::ElementPtr initial_messages,
+                isc::data::ElementPtr subscriptions,
+                isc::data::ElementPtr msg_queue);
+    virtual ~FakeSession();
+
+    virtual void startRead(boost::function<void()> read_callback);
+
+    virtual void establish(const char* socket_file = NULL);
+    bool connect();
+    virtual void disconnect();
+    void sendmsg(isc::data::ElementPtr& msg);
+    void sendmsg(isc::data::ElementPtr& env,
+                 isc::data::ElementPtr& msg);
+    bool recvmsg(isc::data::ElementPtr& msg,
+                 bool nonblock = true, int seq = -1);
+    bool recvmsg(isc::data::ElementPtr& env,
+                 isc::data::ElementPtr& msg,
+                 bool nonblock = true, int seq = -1);
+    virtual void subscribe(std::string group,
                            std::string instance = "*");
                            std::string instance = "*");
-            void unsubscribe(std::string group,
+    virtual void unsubscribe(std::string group,
                              std::string instance = "*");
                              std::string instance = "*");
-            unsigned int group_sendmsg(isc::data::ElementPtr msg,
-                                       std::string group,
-                                       std::string instance = "*",
-                                       std::string to = "*");
-            bool group_recvmsg(isc::data::ElementPtr& envelope,
+    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,
                                isc::data::ElementPtr& msg,
                                bool nonblock = true,
                                bool nonblock = true,
                                int seq = -1);
                                int seq = -1);
-            unsigned int reply(isc::data::ElementPtr& envelope,
-                               isc::data::ElementPtr& newmsg);
-            bool hasQueuedMsgs();
-
-        };
-    } // namespace cc
+    virtual int reply(isc::data::ElementPtr& envelope,
+                      isc::data::ElementPtr& newmsg);
+    virtual bool hasQueuedMsgs();
+    isc::data::ElementPtr getFirstMessage(std::string& group, std::string& to);
+    void addMessage(isc::data::ElementPtr, const std::string& group,
+                    const std::string& to);
+    bool haveSubscription(const std::string& group,
+                          const std::string& instance);
+    bool haveSubscription(const isc::data::ElementPtr group,
+                          const isc::data::ElementPtr instance);
+
+    // For the convenience of tests, we share these internal members
+    // with the tester.  The test code may insert update and check,
+    // before (via the constructor parameters), during and after the actual
+    // session object was created/destroyed.
+    isc::data::ElementPtr getMessages() { return (messages_); }
+    isc::data::ElementPtr getMsgQueue() { return (msg_queue_); }
+
+private:
+    const isc::data::ElementPtr messages_;
+    isc::data::ElementPtr subscriptions_;
+    isc::data::ElementPtr msg_queue_;
+};
+} // namespace cc
 } // namespace isc
 } // namespace isc
 
 
-#endif // _ISC_SESSION_H
+#endif // _ISC_FAKESESSION_H
 
 
 // Local Variables:
 // Local Variables:
 // mode: c++
 // mode: c++