C++ベースのLightweightなHTTPサーバー
| Revision | 5201a3954ea0f6a36ff5f8828af6f211ce3ffff3 (tree) |
|---|---|
| Time | 2013-01-12 23:52:06 |
| Author | Michio Hirai <smg_ykz@user...> |
| Commiter | Michio Hirai |
[Refactor] Refine unit testing for cm::SocketServer and cm::SocketClient (further refinement needed)
| @@ -49,7 +49,7 @@ SocketIf* SocketClient::doConnect(const char* server_name, unsigned short port) | ||
| 49 | 49 | assert(false); |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | - return new Socket(retval); | |
| 52 | + return new Socket(fd_); | |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | 55 | } // namespace cm |
| @@ -1,33 +1,138 @@ | ||
| 1 | 1 | |
| 2 | +#include <vector> | |
| 3 | +#include <iostream> | |
| 4 | + | |
| 2 | 5 | #include "gtest/gtest.h" |
| 3 | 6 | |
| 4 | -#include "cm_socket.h" | |
| 7 | +#include "cm_thread.h" | |
| 8 | +#include "mt_auto_ptr.h" | |
| 9 | +#include "cm_socket_if.h" | |
| 5 | 10 | #include "cm_socket_server.h" |
| 11 | +#include "cm_socket_client.h" | |
| 6 | 12 | #include "cm_event.h" |
| 13 | +#include "mt_range.h" | |
| 14 | + | |
| 15 | +namespace { | |
| 7 | 16 | |
| 8 | -class CmSocketServerTest : public ::testing::Test | |
| 17 | +struct FindSocket | |
| 9 | 18 | { |
| 10 | -protected: | |
| 11 | - CmSocketServerTest() | |
| 12 | - : server_(cm::SOCKET_TYPE_INET_STREAM, "0.0.0.0", 8888), event_(cm::Event::tsdInstance()), | |
| 13 | - socket_() | |
| 19 | + FindSocket(cm::SocketIf& socket_if) | |
| 20 | + : socket_if_(socket_if) | |
| 21 | + {} | |
| 22 | + | |
| 23 | + template <typename InputIterator> | |
| 24 | + InputIterator operator()(InputIterator begin, const InputIterator& end) | |
| 14 | 25 | { |
| 15 | - event_.addHandlerRead(*this, &CmSocketServerTest::accept, server_); | |
| 26 | + for (; begin != end; ++begin) { | |
| 27 | + if (*begin == &socket_if_) { | |
| 28 | + return begin; | |
| 29 | + } | |
| 30 | + } | |
| 31 | + return end; | |
| 32 | + } | |
| 33 | + | |
| 34 | + const cm::SocketIf& socket_if_; | |
| 35 | +}; | |
| 36 | + | |
| 37 | +class CmSocketServerThread | |
| 38 | +{ | |
| 39 | +public: | |
| 40 | + CmSocketServerThread() | |
| 41 | + : server_(cm::SOCKET_TYPE_INET_STREAM, "0.0.0.0", 8888), | |
| 42 | + event_(cm::Event::tsdInstance()), | |
| 43 | + accepted_sockets_() | |
| 44 | + { | |
| 45 | + event_.addHandlerRead(*this, &CmSocketServerThread::accept, server_); | |
| 16 | 46 | } |
| 17 | 47 | |
| 18 | 48 | bool accept(cm::SocketServer& server) |
| 19 | 49 | { |
| 20 | - EXPECT_EQ(&server, &server_); | |
| 21 | - socket_ = server.accept(); | |
| 22 | - return true; | |
| 50 | + std::cout << __FUNCTION__ << " entry" << std::endl; | |
| 51 | + mt::AutoPtr<cm::SocketIf> sock = server.accept(); | |
| 52 | + cm::SocketIf* socket_ptr = sock.get(); | |
| 53 | + event_.addHandlerRead(*this, &CmSocketServerThread::readSocket, *socket_ptr); | |
| 54 | + accepted_sockets_.push_back(socket_ptr); | |
| 55 | + sock.release(); | |
| 56 | + return false; | |
| 57 | + } | |
| 58 | + | |
| 59 | + bool readSocket(cm::SocketIf& socket) | |
| 60 | + { | |
| 61 | + std::cout << __FUNCTION__ << " entry" << std::endl; | |
| 62 | + | |
| 63 | + char buffer[20]; | |
| 64 | + size_t bytes_read = 0u; | |
| 65 | + if (socket.read(bytes_read, buffer, sizeof(buffer))) { | |
| 66 | + std::cout << "received " << buffer << std::endl; | |
| 67 | + } | |
| 68 | + else { | |
| 69 | + std::cout << "closing socket " << socket.getFD() << std::endl; | |
| 70 | + | |
| 71 | + FindSocket socket_finder(socket); | |
| 72 | + std::vector<cm::SocketIf*>::iterator it = socket_finder(mt::begin(accepted_sockets_), | |
| 73 | + mt::end(accepted_sockets_)); | |
| 74 | + delete *it; | |
| 75 | + accepted_sockets_.erase(it); | |
| 76 | + } | |
| 77 | + return false; | |
| 78 | + } | |
| 79 | + | |
| 80 | + void run() | |
| 81 | + { | |
| 82 | + unsigned int count = 0u; | |
| 83 | + while (count < 4) { | |
| 84 | + std::cout << "Count " << count << std::endl; | |
| 85 | + event_.pend(); | |
| 86 | + ++count; | |
| 87 | + } | |
| 23 | 88 | } |
| 24 | 89 | |
| 90 | +private: | |
| 25 | 91 | cm::SocketServer server_; |
| 26 | 92 | cm::Event& event_; |
| 93 | + std::vector<cm::SocketIf*> accepted_sockets_; | |
| 94 | +}; | |
| 95 | + | |
| 96 | +class CmSocketClientThread | |
| 97 | +{ | |
| 98 | +public: | |
| 99 | + CmSocketClientThread() | |
| 100 | + : client_(cm::SOCKET_TYPE_INET_STREAM), event_(cm::Event::tsdInstance()), | |
| 101 | + socket_() | |
| 102 | + { | |
| 103 | + socket_ = client_.connect("127.0.0.1", 8888); | |
| 104 | + } | |
| 105 | + | |
| 106 | + void run() | |
| 107 | + { | |
| 108 | + char buffer[20]; | |
| 109 | + memset(buffer, 0, sizeof(buffer)); | |
| 110 | + strcpy(buffer, "hello world!¥n"); | |
| 111 | + size_t bytes_written = 0u; | |
| 112 | + socket_->write(bytes_written, buffer, sizeof(buffer)); | |
| 113 | + memset(buffer, 0, sizeof(buffer)); | |
| 114 | + strcpy(buffer, "good bye world!¥n"); | |
| 115 | + socket_->write(bytes_written, buffer, sizeof(buffer)); | |
| 116 | + socket_.reset(); | |
| 117 | + } | |
| 118 | + | |
| 119 | +private: | |
| 120 | + cm::SocketClient client_; | |
| 121 | + cm::Event& event_; | |
| 27 | 122 | mt::AutoPtr<cm::SocketIf> socket_; |
| 28 | 123 | }; |
| 29 | 124 | |
| 30 | -TEST_F(CmSocketServerTest, inet_anyaddr) | |
| 125 | + | |
| 126 | +TEST(CmSocketServerTest, inet_anyaddr) | |
| 31 | 127 | { |
| 32 | - event_.pend(); | |
| 128 | + cm::Thread<CmSocketServerThread> server_thread("server_thread"); | |
| 129 | + server_thread.create(); | |
| 130 | + | |
| 131 | + CmSocketClientThread client; | |
| 132 | + | |
| 133 | + client.run(); | |
| 134 | + | |
| 135 | + server_thread.join(); | |
| 33 | 136 | } |
| 137 | + | |
| 138 | +} // namespace |
| @@ -12,6 +12,7 @@ class SocketIf; | ||
| 12 | 12 | |
| 13 | 13 | class SocketClient |
| 14 | 14 | { |
| 15 | +public: | |
| 15 | 16 | SocketClient(SocketType type, bool is_nonblock = false); |
| 16 | 17 | |
| 17 | 18 | virtual ~SocketClient(); |
| @@ -63,8 +63,10 @@ private: | ||
| 63 | 63 | if (SETNAME(thread_arg->tid, thread_arg->name.c_str())) { |
| 64 | 64 | assert(false); |
| 65 | 65 | } |
| 66 | - T obj(thread_arg->arg); | |
| 67 | - obj.run(); | |
| 66 | + { | |
| 67 | + T obj(thread_arg->arg); | |
| 68 | + obj.run(); | |
| 69 | + } | |
| 68 | 70 | pthread_exit(0); |
| 69 | 71 | } |
| 70 | 72 |
| @@ -74,8 +76,10 @@ private: | ||
| 74 | 76 | if (SETNAME(thread_arg->tid, thread_arg->name.c_str())) { |
| 75 | 77 | assert(false); |
| 76 | 78 | } |
| 77 | - T obj; | |
| 78 | - obj.run(); | |
| 79 | + { | |
| 80 | + T obj; | |
| 81 | + obj.run(); | |
| 82 | + } | |
| 79 | 83 | pthread_exit(0); |
| 80 | 84 | } |
| 81 | 85 |