summaryrefslogtreecommitdiffstats
path: root/src/lib/util/unittests/mock_socketsession.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/unittests/mock_socketsession.h')
-rw-r--r--src/lib/util/unittests/mock_socketsession.h151
1 files changed, 151 insertions, 0 deletions
diff --git a/src/lib/util/unittests/mock_socketsession.h b/src/lib/util/unittests/mock_socketsession.h
new file mode 100644
index 0000000..808cddb
--- /dev/null
+++ b/src/lib/util/unittests/mock_socketsession.h
@@ -0,0 +1,151 @@
+// Copyright (C) 2012-2015 Internet Systems Consortium, Inc. ("ISC")
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#ifndef UTIL_UNITTESTS_MOCKSOCKETSESSION_H
+#define UTIL_UNITTESTS_MOCKSOCKETSESSION_H 1
+
+#include <exceptions/exceptions.h>
+
+#include <util/io/socketsession.h>
+#include <util/io/sockaddr_util.h>
+
+#include <cassert>
+#include <cstring>
+#include <vector>
+
+#include <sys/socket.h>
+#include <stdint.h>
+
+namespace isc {
+namespace util {
+namespace unittests {
+
+/// \brief Mock socket session forwarder.
+///
+/// It emulates the behavior of SocketSessionForwarder without involving
+/// network communication, and allowing the tester to customize the behavior
+/// and to examine forwarded data afterwards.
+class MockSocketSessionForwarder :
+ public isc::util::io::BaseSocketSessionForwarder
+{
+public:
+ MockSocketSessionForwarder() :
+ is_connected_(false), connect_ok_(true), push_ok_(true),
+ close_ok_(true),
+ // These are not used until set, but we set them anyway here,
+ // partly to silence cppcheck, and partly to be cleaner. Put some
+ // invalid values in.
+ pushed_sock_(-1), pushed_family_(-1), pushed_type_(-1),
+ pushed_protocol_(-1)
+ {}
+
+ virtual void connectToReceiver() {
+ if (!connect_ok_) {
+ isc_throw(isc::util::io::SocketSessionError, "socket session "
+ "forwarding connection disabled for test");
+ }
+ if (is_connected_) {
+ isc_throw(isc::util::io::SocketSessionError, "duplicate connect");
+ }
+ is_connected_ = true;
+ }
+ virtual void close() {
+ if (!is_connected_) {
+ isc_throw(isc::util::io::SocketSessionError, "duplicate close");
+ }
+ is_connected_ = false;
+ }
+
+ // Pushing a socket session. It copies the given session data
+ // so that the test code can check the values later via the getter
+ // methods. Complete deep copy will be created, so the caller doesn't
+ // have to keep the parameters valid after the call to this method.
+ virtual void push(int sock, int family, int type, int protocol,
+ const struct sockaddr& local_end,
+ const struct sockaddr& remote_end,
+ const void* data, size_t data_len)
+ {
+ if (!push_ok_) {
+ isc_throw(isc::util::io::SocketSessionError,
+ "socket session forwarding is disabled for test");
+ }
+ if (!is_connected_) {
+ isc_throw(isc::util::io::SocketSessionError,
+ "socket session is being pushed before connected");
+ }
+
+ // Copy parameters for later checks
+ pushed_sock_ = sock;
+ pushed_family_ = family;
+ pushed_type_ = type;
+ pushed_protocol_ = protocol;
+ assert(io::internal::getSALength(local_end) <=
+ sizeof(pushed_local_end_ss_));
+ std::memcpy(&pushed_local_end_ss_, &local_end,
+ io::internal::getSALength(local_end));
+ assert(io::internal::getSALength(remote_end) <=
+ sizeof(pushed_remote_end_ss_));
+ std::memcpy(&pushed_remote_end_ss_, &remote_end,
+ io::internal::getSALength(remote_end));
+ pushed_data_.resize(data_len);
+ std::memcpy(&pushed_data_[0], data, data_len);
+ }
+
+ // Allow the test code to check if the connection is established.
+ bool isConnected() const { return (is_connected_); }
+
+ // Allow the test code to customize the forwarder behavior wrt whether
+ // a specific operation should succeed or fail.
+ void disableConnect() { connect_ok_ = false; }
+ void enableConnect() { connect_ok_ = true; }
+ void disableClose() { close_ok_ = false; }
+ void disablePush() { push_ok_ = false; }
+ void enablePush() { push_ok_ = true; }
+
+ // Read-only accessors to recorded parameters to the previous successful
+ // call to push(). Return values are undefined if there has been no
+ // successful call to push().
+ // Note that we use convertSockAddr() to convert sockaddr_storage to
+ // sockaddr. It should be safe since we use the storage in its literal
+ // sense; it was originally filled with the binary image of another
+ // sockaddr structure, and we are going to return the image opaquely
+ // as a sockaddr structure without touching the data.
+ int getPushedSock() const { return (pushed_sock_); }
+ int getPushedFamily() const { return (pushed_family_); }
+ int getPushedType() const { return (pushed_type_); }
+ int getPushedProtocol() const { return (pushed_protocol_); }
+ const struct sockaddr& getPushedLocalend() const {
+ return (*io::internal::convertSockAddr(&pushed_local_end_ss_));
+ }
+ const struct sockaddr& getPushedRemoteend() const {
+ return (*io::internal::convertSockAddr(&pushed_remote_end_ss_));
+ }
+ const std::vector<uint8_t>& getPushedData() const {
+ return (pushed_data_);
+ }
+
+private:
+ bool is_connected_;
+ bool connect_ok_;
+ bool push_ok_;
+ bool close_ok_;
+ int pushed_sock_;
+ int pushed_family_;
+ int pushed_type_;
+ int pushed_protocol_;
+ struct sockaddr_storage pushed_local_end_ss_;
+ struct sockaddr_storage pushed_remote_end_ss_;
+ std::vector<uint8_t> pushed_data_;
+};
+
+} // end of unittests
+} // end of util
+} // end of isc
+#endif // UTIL_UNITTESTS_MOCKSOCKETSESSION_H
+
+// Local Variables:
+// mode: c++
+// End: