diff options
-rw-r--r-- | src/lib/asiolink/Makefile.am | 3 | ||||
-rw-r--r-- | src/lib/asiolink/asiolink.h | 2 | ||||
-rw-r--r-- | src/lib/asiolink/io_message.h | 102 | ||||
-rw-r--r-- | src/lib/asiolink/local_socket.cc | 102 | ||||
-rw-r--r-- | src/lib/asiolink/local_socket.h | 132 | ||||
-rw-r--r-- | src/lib/asiolink/simple_callback.h | 75 | ||||
-rw-r--r-- | src/lib/asiolink/tests/Makefile.am | 1 | ||||
-rw-r--r-- | src/lib/asiolink/tests/local_socket_unittest.cc | 253 |
8 files changed, 0 insertions, 670 deletions
diff --git a/src/lib/asiolink/Makefile.am b/src/lib/asiolink/Makefile.am index a6531363ba..53f960f18b 100644 --- a/src/lib/asiolink/Makefile.am +++ b/src/lib/asiolink/Makefile.am @@ -24,15 +24,12 @@ libkea_asiolink_la_SOURCES += io_address.cc io_address.h libkea_asiolink_la_SOURCES += io_asio_socket.h libkea_asiolink_la_SOURCES += io_endpoint.cc io_endpoint.h libkea_asiolink_la_SOURCES += io_error.h -libkea_asiolink_la_SOURCES += io_message.h libkea_asiolink_la_SOURCES += io_service.h io_service.cc libkea_asiolink_la_SOURCES += io_socket.h io_socket.cc -libkea_asiolink_la_SOURCES += simple_callback.h libkea_asiolink_la_SOURCES += tcp_endpoint.h libkea_asiolink_la_SOURCES += tcp_socket.h libkea_asiolink_la_SOURCES += udp_endpoint.h libkea_asiolink_la_SOURCES += udp_socket.h -libkea_asiolink_la_SOURCES += local_socket.h local_socket.cc # Note: the ordering matters: -Wno-... must follow -Wextra (defined in # KEA_CXXFLAGS) diff --git a/src/lib/asiolink/asiolink.h b/src/lib/asiolink/asiolink.h index cc8aa7af36..5a33983f76 100644 --- a/src/lib/asiolink/asiolink.h +++ b/src/lib/asiolink/asiolink.h @@ -20,12 +20,10 @@ // See the description of the namespace below. #include <asiolink/io_service.h> -#include <asiolink/simple_callback.h> #include <asiolink/interval_timer.h> #include <asiolink/io_address.h> #include <asiolink/io_endpoint.h> -#include <asiolink/io_message.h> #include <asiolink/io_socket.h> #include <asiolink/io_error.h> diff --git a/src/lib/asiolink/io_message.h b/src/lib/asiolink/io_message.h deleted file mode 100644 index 7607c72ed5..0000000000 --- a/src/lib/asiolink/io_message.h +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef IO_MESSAGE_H -#define IO_MESSAGE_H 1 - -// IMPORTANT NOTE: only very few ASIO headers files can be included in -// this file. In particular, asio.hpp should never be included here. -// See the description of the namespace below. -#include <unistd.h> // for some network system calls - -#include <functional> -#include <string> - -#include <exceptions/exceptions.h> - -#include <asiolink/io_endpoint.h> -#include <asiolink/io_socket.h> - -namespace isc { -namespace asiolink { - -/// \brief The \c IOMessage class encapsulates an incoming message received -/// on a socket. -/// -/// An \c IOMessage object represents a tuple of a chunk of data -/// (a UDP packet or some segment of TCP stream), the socket over which the -/// data is passed, the information about the other end point of the -/// communication, and perhaps more. -/// -/// The current design and interfaces of this class is tentative. -/// It only provides a minimal level of support that is necessary for -/// the current implementation of the authoritative server. -/// A future version of this class will definitely support more. -class IOMessage { - /// - /// \name Constructors and Destructor - /// - - /// Note: The copy constructor and the assignment operator are - /// intentionally defined as private, making this class non-copyable. - //@{ -private: - IOMessage(const IOMessage& source); - IOMessage& operator=(const IOMessage& source); -public: - /// \brief Constructor from message data - /// - /// This constructor needs to handle the ASIO \c ip::address class, - /// and is intended to be used within this wrapper implementation. - /// Once the \c IOMessage object is created, the application can - /// get access to the information via the wrapper interface such as - /// \c getRemoteAddress(). - /// - /// This constructor never throws an exception. - /// - /// \param data A pointer to the message data. - /// \param data_size The size of the message data in bytes. - /// \param io_socket The socket over which the data is given. - /// \param remote_endpoint The other endpoint of the socket, that is, - /// the sender of the message. - IOMessage(const void* data, const size_t data_size, - const IOSocket& io_socket, const IOEndpoint& remote_endpoint) : - data_(data), data_size_(data_size), io_socket_(io_socket), - remote_endpoint_(remote_endpoint) - {} - //@} - - /// \brief Returns a pointer to the received data. - const void* getData() const { return (data_); } - - /// \brief Returns the size of the received data in bytes. - size_t getDataSize() const { return (data_size_); } - - /// \brief Returns the socket on which the message arrives. - const IOSocket& getSocket() const { return (io_socket_); } - - /// \brief Returns the endpoint that sends the message. - const IOEndpoint& getRemoteEndpoint() const { return (remote_endpoint_); } - -private: - const void* data_; - const size_t data_size_; - const IOSocket& io_socket_; - const IOEndpoint& remote_endpoint_; -}; - - -} // namespace asiolink -} // namespace isc -#endif // IO_MESSAGE_H diff --git a/src/lib/asiolink/local_socket.cc b/src/lib/asiolink/local_socket.cc deleted file mode 100644 index f47226e837..0000000000 --- a/src/lib/asiolink/local_socket.cc +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include <asiolink/local_socket.h> -#include <asiolink/io_service.h> -#include <asiolink/io_error.h> - -#include <asio.hpp> - -#include <boost/bind.hpp> - -#include <string> -#include <sys/socket.h> - -namespace isc { -namespace asiolink { -class LocalSocket::Impl { -public: - Impl(IOService& io_service, int fd) : - asio_sock_(io_service.get_io_service(), - asio::local::stream_protocol(), fd) - { - // Depending on the underlying demultiplex API, the constructor may or - // may not throw in case fd is invalid. To catch such cases sooner, - // we try to get the local endpoint (we don't need it in the rest of - // this implementation). - asio_sock_.local_endpoint(ec_); - if (ec_) { - isc_throw(IOError, "failed to open local socket with FD " << fd - << " (local endpoint unknown): " << ec_.message()); - } - } - - asio::local::stream_protocol::socket asio_sock_; - asio::error_code ec_; -}; - -LocalSocket::LocalSocket(IOService& io_service, int fd) : - impl_(NULL) -{ - try { - impl_ = new Impl(io_service, fd); - } catch (const asio::system_error& error) { - // Catch and convert any exception from asio's constructor - isc_throw(IOError, "failed to open local socket with FD " << fd - << ": " << error.what()); - } -} - -LocalSocket::~LocalSocket() { - delete impl_; -} - -int -LocalSocket::getNative() const { - return (impl_->asio_sock_.native()); -} - -int -LocalSocket::getProtocol() const { - return (AF_UNIX); -} - -namespace { -// Wrapper callback for async_read that simply adjusts asio-native parameters -// for the LocalSocket interface. Note that this is a free function and -// doesn't rely on internal member variables of LocalSocket. -// So it can be called safely even after the LocalSocket object on which -// asyncRead() was called is destroyed. -void -readCompleted(const asio::error_code& ec, - LocalSocket::ReadCallback user_callback) -{ - // assumption check: we pass non empty string iff ec indicates an error. - const std::string err_msg = ec ? ec.message() : std::string(); - assert(ec || err_msg.empty()); - - user_callback(err_msg); -} -} - -void -LocalSocket::asyncRead(const ReadCallback& callback, void* buf, - size_t buflen) -{ - asio::async_read(impl_->asio_sock_, asio::buffer(buf, buflen), - boost::bind(readCompleted, _1, callback)); -} - -} // namespace asiolink -} // namespace isc diff --git a/src/lib/asiolink/local_socket.h b/src/lib/asiolink/local_socket.h deleted file mode 100644 index 6269b7c9af..0000000000 --- a/src/lib/asiolink/local_socket.h +++ /dev/null @@ -1,132 +0,0 @@ -// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef LOCAL_SOCKET_H -#define LOCAL_SOCKET_H 1 - -#include <asiolink/io_socket.h> -#include <asiolink/io_service.h> - -#include <boost/noncopyable.hpp> - -namespace isc { -namespace asiolink { - -/// \brief A wrapper for ASIO stream socket in the local (AF_UNIX) domain. -/// -/// This class provides a simple, limited set of wrapper interfaces to an -/// ASIO stream socket object in the local domain. Unlike other concrete -/// derived classes of \c IOSocket, this class is intended to be instantiated -/// directly. Right now it only provides read interface due to the limited -/// expected usage, but it can be extended as we see need for other operations -/// on this socket. -/// -/// Note that in the initial implementation there's even no stop() or cancel() -/// method; for these cases users are expected to just destroy the socket -/// object (this may be extended in future, too). -class LocalSocket : boost::noncopyable, public IOSocket { -public: - /// \brief Constructor from a native file descriptor of AF_UNIX stream - /// socket. - /// - /// Parameter \c fd must be an open stream-type socket of the AF_UNIX - /// domain. The constructor tries to detect some invalid cases, but - /// it may not reject all invalid cases. It's generally the - /// responsibility of the caller. - /// - /// \throw IOError Failed to create the socket object, most likely because - /// the given file descriptor is invalid. - /// - /// \param io_service The IO service object to handle events on this - /// socket. - /// \param fd File descriptor of an AF_UNIX socket. - LocalSocket(IOService& io_service, int fd); - - /// \brief Destructor. - /// - /// \throw None. - virtual ~LocalSocket(); - - /// \brief Local socket version of getNative(). - /// - /// \throw None. - virtual int getNative() const; - - /// \brief Local socket version of getProtocol(). - /// - /// It always returns \c AF_UNIX. - /// - /// \throw None. - virtual int getProtocol() const; - - /// \brief The callback functor for the \c asyncRead method. - /// - /// The callback takes one parameter, \c error. It will be set to - /// non empty string if read operation fails and the string explains - /// the reason for the failure. On success \c error will be empty. - typedef boost::function<void(const std::string& error)> ReadCallback; - - /// \brief Start asynchronous read on the socket. - /// - /// This method registers an interest on a new read event on the local - /// socket for the specified length of data (\c buflen bytes). This - /// method returns immediately. When the specified amount of data - /// are available for read from the socket or an error happens, the - /// specified callback will be called. In the former case the data are - /// copied into the given buffer (pointed to by \c buf); in the latter - /// case, the \c error parameter of the callback will be set to a non - /// empty string. - /// - /// In the case of error, this socket should be considered - /// unusable anymore, because this class doesn't provide a feasible way - /// to identify where in the input stream to restart reading. So, - /// in practice, the user of this socket should destroy this socket, - /// and, if necessary to continue, create a new one. - /// - /// \c buf must point to a memory region that has at least \c buflen - /// bytes of valid space. That region must be kept valid until the - /// callback is called or the \c IOService passed to the constructor - /// is stopped. This method and class do not check these conditions; - /// it's the caller's responsibility to guarantee them. - /// - /// \note If asyncRead() has been called and hasn't been completed (with - /// the callback being called), it's possible that the callback is called - /// even after the \c LocalSocket object is destroyed. So the caller - /// has to make sure that either \c LocalSocket is valid until the - /// callback is called or the callback does not depend on \c LocalSocket; - /// alternatively, the caller can stop the \c IOService. This will make - /// sure the callback will not be called regardless of when and how - /// the \c LocalSocket is destroyed. - /// - /// \throw None. - /// - /// \brief callback The callback functor to be called on the completion - /// of read. - /// \brief buf Buffer to read in data from the socket. - /// \brief buflen Length of data to read. - void asyncRead(const ReadCallback& callback, void* buf, size_t buflen); - -private: - class Impl; - Impl* impl_; -}; - -} // namespace asiolink -} // namespace isc - -#endif // LOCAL_SOCKET_H - -// Local Variables: -// mode: c++ -// End: diff --git a/src/lib/asiolink/simple_callback.h b/src/lib/asiolink/simple_callback.h deleted file mode 100644 index 4301bd1d48..0000000000 --- a/src/lib/asiolink/simple_callback.h +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2011 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#ifndef ASIOLINK_SIMPLE_CALLBACK_H -#define ASIOLINK_SIMPLE_CALLBACK_H 1 - -#include <asiolink/io_message.h> - -namespace isc { -namespace asiolink { - -/// \brief The \c SimpleCallback class is an abstract base class for a -/// simple callback function with the signature: -/// -/// void simpleCallback(const IOMessage& io_message) const; -/// -/// Specific derived class implementations are hidden within the -/// implementation. Instances of the derived classes can be called -/// as functions via the operator() interface. Pointers to these -/// instances can then be provided to the \c IOService class -/// via its constructor. -/// -/// The \c SimpleCallback is expected to be used for basic, generic -/// tasks such as checking for configuration changes. It may also be -/// used for testing purposes. -class SimpleCallback { - /// - /// \name Constructors and Destructor - /// - /// Note: The copy constructor and the assignment operator are - /// intentionally defined as private, making this class non-copyable. - //@{ -private: - SimpleCallback(const SimpleCallback& source); - SimpleCallback& operator=(const SimpleCallback& source); -protected: - /// \brief The default constructor. - /// - /// This is intentionally defined as \c protected as this base class - /// should never be instantiated (except as part of a derived class). - SimpleCallback() { - self_ = this; - } -public: - /// \brief The destructor - virtual ~SimpleCallback() {} - /// \brief The function operator - //@} - /// - /// This makes its call indirectly via the "self" pointer, ensuring - /// that the function ultimately invoked will be the one in the derived - /// class. - /// - /// \param io_message The event message to handle - virtual void operator()(const IOMessage& io_message) const { - (*self_)(io_message); - } -private: - SimpleCallback* self_; -}; - -} // namespace asiolink -} // namespace isc -#endif // ASIOLINK_SIMPLE_CALLBACK_H diff --git a/src/lib/asiolink/tests/Makefile.am b/src/lib/asiolink/tests/Makefile.am index fe6d76575c..90752f5ca8 100644 --- a/src/lib/asiolink/tests/Makefile.am +++ b/src/lib/asiolink/tests/Makefile.am @@ -34,7 +34,6 @@ run_unittests_SOURCES += tcp_socket_unittest.cc run_unittests_SOURCES += udp_endpoint_unittest.cc run_unittests_SOURCES += udp_socket_unittest.cc run_unittests_SOURCES += io_service_unittest.cc -run_unittests_SOURCES += local_socket_unittest.cc run_unittests_SOURCES += dummy_io_callback_unittest.cc run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) diff --git a/src/lib/asiolink/tests/local_socket_unittest.cc b/src/lib/asiolink/tests/local_socket_unittest.cc deleted file mode 100644 index 72efd6e97d..0000000000 --- a/src/lib/asiolink/tests/local_socket_unittest.cc +++ /dev/null @@ -1,253 +0,0 @@ -// Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC") -// -// Permission to use, copy, modify, and/or distribute this software for any -// purpose with or without fee is hereby granted, provided that the above -// copyright notice and this permission notice appear in all copies. -// -// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH -// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY -// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, -// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM -// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE -// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR -// PERFORMANCE OF THIS SOFTWARE. - -#include <asiolink/local_socket.h> -#include <asiolink/io_error.h> - -#include <gtest/gtest.h> - -#include <boost/noncopyable.hpp> -#include <boost/scoped_ptr.hpp> -#include <boost/bind.hpp> - -#include <csignal> -#include <cstring> -#include <vector> - -#include <sys/socket.h> -#include <stdint.h> -#include <unistd.h> // for alarm(3) - -using namespace isc::asiolink; - -namespace { - -// duration (in seconds) until we break possible hangup; value is an -// arbitrary choice. -const unsigned IO_TIMEOUT = 10; - -// A simple RAII wrapper for a file descriptor so test sockets are safely -// closed in each test. -class ScopedSocket : boost::noncopyable { -public: - ScopedSocket() : fd_(-1) {} - ~ScopedSocket() { - if (fd_ >= 0) { - EXPECT_EQ(0, ::close(fd_)); - } - } - void set(int fd) { - assert(fd_ == -1); - fd_ = fd; - } - int get() { return (fd_); } - int release() { - const int ret = fd_; - fd_ = -1; - return (ret); - } -private: - int fd_; -}; - -class LocalSocketTest : public ::testing::Test { -protected: - LocalSocketTest() { - int sock_pair[2]; - EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair)); - sock_pair_[0].set(sock_pair[0]); - sock_pair_[1].set(sock_pair[1]); - - // For tests using actual I/O we use a timer to prevent hangup - // due to a bug. Set up the signal handler for the timer here. - g_io_service_ = &io_service_; - prev_handler_ = std::signal(SIGALRM, stopIOService); - } - - ~LocalSocketTest() { - alarm(0); - // reset the global to NULL to detect any invalid access to freed - // io_service (this shouldn't happen, so we don't change stopIOService - // itself) - g_io_service_ = NULL; - std::signal(SIGALRM, prev_handler_); - } - - // Common set of tests for async read - void checkAsyncRead(size_t data_len); - - IOService io_service_; - ScopedSocket sock_pair_[2]; - std::vector<uint8_t> read_buf_; -private: - static IOService* g_io_service_; // will be set to &io_service_ - void (*prev_handler_)(int); - - // SIGALRM handler to prevent hangup. This must be a static method - // so it can be passed to std::signal(). - static void stopIOService(int) { - g_io_service_->stop(); - } -}; - -IOService* LocalSocketTest::g_io_service_ = NULL; - -TEST_F(LocalSocketTest, construct) { - const int fd = sock_pair_[0].release(); - LocalSocket sock(io_service_, fd); - EXPECT_EQ(fd, sock.getNative()); - EXPECT_EQ(AF_UNIX, sock.getProtocol()); -} - -TEST_F(LocalSocketTest, constructError) { - // try to construct a LocalSocket object with a closed socket. It should - // fail. - const int fd = sock_pair_[0].release(); - EXPECT_EQ(0, close(fd)); - EXPECT_THROW(LocalSocket(io_service_, fd), IOError); -} - -TEST_F(LocalSocketTest, autoClose) { - // Confirm that passed FD will be closed on destruction of LocalSocket - const int fd = sock_pair_[0].release(); - { - LocalSocket sock(io_service_, fd); - } - // fd should have been closed, so close() should fail (we assume there's - // no other open() call since then) - EXPECT_EQ(-1, ::close(fd)); -} - -void -callback(const std::string& error, IOService* io_service, bool* called, - bool expect_error) -{ - if (expect_error) { - EXPECT_NE("", error); - } else { - EXPECT_EQ("", error); - } - *called = true; - io_service->stop(); -} - -void -LocalSocketTest::checkAsyncRead(size_t data_len) { - LocalSocket sock(io_service_, sock_pair_[0].release()); - bool callback_called = false; - read_buf_.resize(data_len); - sock.asyncRead(boost::bind(&callback, _1, &io_service_, &callback_called, - false), &read_buf_[0], data_len); - - std::vector<uint8_t> expected_data(data_len); - for (size_t i = 0; i < data_len; ++i) { - expected_data[i] = i & 0xff; - } - alarm(IO_TIMEOUT); - // If write blocks, it will eventually fail due to signal interruption. - // Since io_service has been stopped already, run() would immediately - // return and test should complete (with failure). But to make very sure - // it never cause hangup we rather return from the test at the point of - // failure of write. In either case it signals a failure and need for - // a fix. - ASSERT_EQ(data_len, write(sock_pair_[1].get(), &expected_data[0], - data_len)); - io_service_.run(); - EXPECT_TRUE(callback_called); - EXPECT_EQ(0, std::memcmp(&expected_data[0], &read_buf_[0], data_len)); - -} - -TEST_F(LocalSocketTest, asyncRead) { - // A simple case of asynchronous read: wait for 1 byte and successfully - // read it in the run() loop. - checkAsyncRead(1); -} - -TEST_F(LocalSocketTest, asyncLargeRead) { - // Similar to the previous case, but for moderately larger data. - // (for the moment) we don't expect to use this interface with much - // larger data that could cause blocking write. - checkAsyncRead(1024); -} - -TEST_F(LocalSocketTest, asyncPartialRead) { - alarm(IO_TIMEOUT); - - // specify reading 4 bytes of data, and send 3 bytes. It shouldn't cause - // callback. while we actually don't use the buffer, we'll initialize it - // to make valgrind happy. - char recv_buf[4]; - std::memset(recv_buf, 0, sizeof(recv_buf)); - bool callback_called = false; - LocalSocket sock(io_service_, sock_pair_[0].release()); - sock.asyncRead(boost::bind(&callback, _1, &io_service_, &callback_called, - false), recv_buf, sizeof(recv_buf)); - EXPECT_EQ(3, write(sock_pair_[1].get(), recv_buf, 3)); - - // open another pair of sockets so we can stop the IO service after run. - int socks[2]; - char ch = 0; - EXPECT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM, 0, socks)); - ScopedSocket aux_sockpair[2]; - aux_sockpair[0].set(socks[0]); - aux_sockpair[1].set(socks[1]); - LocalSocket aux_sock(io_service_, aux_sockpair[0].get()); - aux_sockpair[0].release(); // on successful construction we should release - bool aux_callback_called = false; - aux_sock.asyncRead(boost::bind(&callback, _1, &io_service_, - &aux_callback_called, false), &ch, 1); - EXPECT_EQ(1, write(aux_sockpair[1].get(), &ch, 1)); - - // run the IO service, it will soon be stopped via the auxiliary callback. - // the main callback shouldn't be called. - io_service_.run(); - EXPECT_FALSE(callback_called); - EXPECT_TRUE(aux_callback_called); -} - -TEST_F(LocalSocketTest, asyncReadError) { - const int sock_fd = sock_pair_[0].release(); - LocalSocket sock(io_service_, sock_fd); - bool callback_called = false; - read_buf_.resize(1); - read_buf_.at(0) = 53; // dummy data to check it later - const char ch = 35; // send different data to the read socket with data - EXPECT_EQ(1, write(sock_pair_[1].get(), &ch, 1)); - close(sock_fd); // invalidate the read socket - // we'll get callback with an error (e.g. 'bad file descriptor) - sock.asyncRead(boost::bind(&callback, _1, &io_service_, &callback_called, - true), &read_buf_[0], 1); - - io_service_.run(); - EXPECT_TRUE(callback_called); - EXPECT_EQ(53, read_buf_.at(0)); -} - -TEST_F(LocalSocketTest, asyncReadThenDestroy) { - // destroy the socket before running the IO service. we'll still get - // callback with an error. - boost::scoped_ptr<LocalSocket> sock( - new LocalSocket(io_service_, sock_pair_[0].release())); - read_buf_.resize(1); - bool callback_called = false; - sock->asyncRead(boost::bind(&callback, _1, &io_service_, &callback_called, - true), &read_buf_[0], 1); - sock.reset(); - - io_service_.run(); - EXPECT_TRUE(callback_called); -} - -} |