| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/base/listen_socket_unittest.h" | |
| 6 | |
| 7 #include <fcntl.h> | |
| 8 #include <sys/types.h> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/eintr_wrapper.h" | |
| 12 #include "base/sys_byteorder.h" | |
| 13 #include "net/base/net_util.h" | |
| 14 #include "testing/platform_test.h" | |
| 15 | |
| 16 namespace net { | |
| 17 | |
| 18 const int ListenSocketTester::kTestPort = 9999; | |
| 19 | |
| 20 static const int kReadBufSize = 1024; | |
| 21 static const char kHelloWorld[] = "HELLO, WORLD"; | |
| 22 static const int kMaxQueueSize = 20; | |
| 23 static const char kLoopback[] = "127.0.0.1"; | |
| 24 static const int kDefaultTimeoutMs = 5000; | |
| 25 | |
| 26 ListenSocketTester::ListenSocketTester() | |
| 27 : thread_(NULL), | |
| 28 loop_(NULL), | |
| 29 server_(NULL), | |
| 30 connection_(NULL), | |
| 31 cv_(&lock_) { | |
| 32 } | |
| 33 | |
| 34 void ListenSocketTester::SetUp() { | |
| 35 base::Thread::Options options; | |
| 36 options.message_loop_type = MessageLoop::TYPE_IO; | |
| 37 thread_.reset(new base::Thread("socketio_test")); | |
| 38 thread_->StartWithOptions(options); | |
| 39 loop_ = reinterpret_cast<MessageLoopForIO*>(thread_->message_loop()); | |
| 40 | |
| 41 loop_->PostTask(FROM_HERE, base::Bind(&ListenSocketTester::Listen, this)); | |
| 42 | |
| 43 // verify Listen succeeded | |
| 44 NextAction(); | |
| 45 ASSERT_FALSE(server_ == NULL); | |
| 46 ASSERT_EQ(ACTION_LISTEN, last_action_.type()); | |
| 47 | |
| 48 // verify the connect/accept and setup test_socket_ | |
| 49 test_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); | |
| 50 ASSERT_NE(INVALID_SOCKET, test_socket_); | |
| 51 struct sockaddr_in client; | |
| 52 client.sin_family = AF_INET; | |
| 53 client.sin_addr.s_addr = inet_addr(kLoopback); | |
| 54 client.sin_port = base::HostToNet16(kTestPort); | |
| 55 int ret = HANDLE_EINTR( | |
| 56 connect(test_socket_, reinterpret_cast<sockaddr*>(&client), | |
| 57 sizeof(client))); | |
| 58 ASSERT_NE(ret, SOCKET_ERROR); | |
| 59 | |
| 60 NextAction(); | |
| 61 ASSERT_EQ(ACTION_ACCEPT, last_action_.type()); | |
| 62 } | |
| 63 | |
| 64 void ListenSocketTester::TearDown() { | |
| 65 #if defined(OS_WIN) | |
| 66 ASSERT_EQ(0, closesocket(test_socket_)); | |
| 67 #elif defined(OS_POSIX) | |
| 68 ASSERT_EQ(0, HANDLE_EINTR(close(test_socket_))); | |
| 69 #endif | |
| 70 NextAction(); | |
| 71 ASSERT_EQ(ACTION_CLOSE, last_action_.type()); | |
| 72 | |
| 73 loop_->PostTask(FROM_HERE, base::Bind(&ListenSocketTester::Shutdown, this)); | |
| 74 NextAction(); | |
| 75 ASSERT_EQ(ACTION_SHUTDOWN, last_action_.type()); | |
| 76 | |
| 77 thread_.reset(); | |
| 78 loop_ = NULL; | |
| 79 } | |
| 80 | |
| 81 void ListenSocketTester::ReportAction(const ListenSocketTestAction& action) { | |
| 82 base::AutoLock locked(lock_); | |
| 83 queue_.push_back(action); | |
| 84 cv_.Broadcast(); | |
| 85 } | |
| 86 | |
| 87 void ListenSocketTester::NextAction() { | |
| 88 base::AutoLock locked(lock_); | |
| 89 while (queue_.empty()) | |
| 90 cv_.Wait(); | |
| 91 last_action_ = queue_.front(); | |
| 92 queue_.pop_front(); | |
| 93 } | |
| 94 | |
| 95 int ListenSocketTester::ClearTestSocket() { | |
| 96 char buf[kReadBufSize]; | |
| 97 int len_ret = 0; | |
| 98 do { | |
| 99 int len = HANDLE_EINTR(recv(test_socket_, buf, kReadBufSize, 0)); | |
| 100 if (len == SOCKET_ERROR || len == 0) { | |
| 101 break; | |
| 102 } else { | |
| 103 len_ret += len; | |
| 104 } | |
| 105 } while (true); | |
| 106 return len_ret; | |
| 107 } | |
| 108 | |
| 109 void ListenSocketTester::Shutdown() { | |
| 110 connection_->Release(); | |
| 111 connection_ = NULL; | |
| 112 server_->Release(); | |
| 113 server_ = NULL; | |
| 114 ReportAction(ListenSocketTestAction(ACTION_SHUTDOWN)); | |
| 115 } | |
| 116 | |
| 117 void ListenSocketTester::Listen() { | |
| 118 server_ = DoListen(); | |
| 119 if (server_) { | |
| 120 server_->AddRef(); | |
| 121 ReportAction(ListenSocketTestAction(ACTION_LISTEN)); | |
| 122 } | |
| 123 } | |
| 124 | |
| 125 void ListenSocketTester::SendFromTester() { | |
| 126 connection_->Send(kHelloWorld); | |
| 127 ReportAction(ListenSocketTestAction(ACTION_SEND)); | |
| 128 } | |
| 129 | |
| 130 void ListenSocketTester::TestClientSend() { | |
| 131 ASSERT_TRUE(Send(test_socket_, kHelloWorld)); | |
| 132 NextAction(); | |
| 133 ASSERT_EQ(ACTION_READ, last_action_.type()); | |
| 134 ASSERT_EQ(last_action_.data(), kHelloWorld); | |
| 135 } | |
| 136 | |
| 137 void ListenSocketTester::TestClientSendLong() { | |
| 138 size_t hello_len = strlen(kHelloWorld); | |
| 139 std::string long_string; | |
| 140 size_t long_len = 0; | |
| 141 for (int i = 0; i < 200; i++) { | |
| 142 long_string += kHelloWorld; | |
| 143 long_len += hello_len; | |
| 144 } | |
| 145 ASSERT_TRUE(Send(test_socket_, long_string)); | |
| 146 size_t read_len = 0; | |
| 147 while (read_len < long_len) { | |
| 148 NextAction(); | |
| 149 ASSERT_EQ(ACTION_READ, last_action_.type()); | |
| 150 std::string last_data = last_action_.data(); | |
| 151 size_t len = last_data.length(); | |
| 152 if (long_string.compare(read_len, len, last_data)) { | |
| 153 ASSERT_EQ(long_string.compare(read_len, len, last_data), 0); | |
| 154 } | |
| 155 read_len += last_data.length(); | |
| 156 } | |
| 157 ASSERT_EQ(read_len, long_len); | |
| 158 } | |
| 159 | |
| 160 void ListenSocketTester::TestServerSend() { | |
| 161 loop_->PostTask(FROM_HERE, base::Bind( | |
| 162 &ListenSocketTester::SendFromTester, this)); | |
| 163 NextAction(); | |
| 164 ASSERT_EQ(ACTION_SEND, last_action_.type()); | |
| 165 const int buf_len = 200; | |
| 166 char buf[buf_len+1]; | |
| 167 unsigned recv_len = 0; | |
| 168 while (recv_len < strlen(kHelloWorld)) { | |
| 169 int r = HANDLE_EINTR(recv(test_socket_, buf, buf_len, 0)); | |
| 170 ASSERT_GE(r, 0); | |
| 171 recv_len += static_cast<unsigned>(r); | |
| 172 if (!r) | |
| 173 break; | |
| 174 } | |
| 175 buf[recv_len] = 0; | |
| 176 ASSERT_STREQ(buf, kHelloWorld); | |
| 177 } | |
| 178 | |
| 179 bool ListenSocketTester::Send(SOCKET sock, const std::string& str) { | |
| 180 int len = static_cast<int>(str.length()); | |
| 181 int send_len = HANDLE_EINTR(send(sock, str.data(), len, 0)); | |
| 182 if (send_len == SOCKET_ERROR) { | |
| 183 LOG(ERROR) << "send failed: " << errno; | |
| 184 return false; | |
| 185 } else if (send_len != len) { | |
| 186 return false; | |
| 187 } | |
| 188 return true; | |
| 189 } | |
| 190 | |
| 191 void ListenSocketTester::DidAccept(ListenSocket *server, | |
| 192 ListenSocket *connection) { | |
| 193 connection_ = connection; | |
| 194 connection_->AddRef(); | |
| 195 ReportAction(ListenSocketTestAction(ACTION_ACCEPT)); | |
| 196 } | |
| 197 | |
| 198 void ListenSocketTester::DidRead(ListenSocket *connection, | |
| 199 const char* data, | |
| 200 int len) { | |
| 201 std::string str(data, len); | |
| 202 ReportAction(ListenSocketTestAction(ACTION_READ, str)); | |
| 203 } | |
| 204 | |
| 205 void ListenSocketTester::DidClose(ListenSocket *sock) { | |
| 206 ReportAction(ListenSocketTestAction(ACTION_CLOSE)); | |
| 207 } | |
| 208 | |
| 209 ListenSocketTester::~ListenSocketTester() {} | |
| 210 | |
| 211 ListenSocket* ListenSocketTester::DoListen() { | |
| 212 return ListenSocket::Listen(kLoopback, kTestPort, this); | |
| 213 } | |
| 214 | |
| 215 class ListenSocketTest: public PlatformTest { | |
| 216 public: | |
| 217 ListenSocketTest() { | |
| 218 tester_ = NULL; | |
| 219 } | |
| 220 | |
| 221 virtual void SetUp() { | |
| 222 PlatformTest::SetUp(); | |
| 223 tester_ = new ListenSocketTester(); | |
| 224 tester_->SetUp(); | |
| 225 } | |
| 226 | |
| 227 virtual void TearDown() { | |
| 228 PlatformTest::TearDown(); | |
| 229 tester_->TearDown(); | |
| 230 tester_ = NULL; | |
| 231 } | |
| 232 | |
| 233 scoped_refptr<ListenSocketTester> tester_; | |
| 234 }; | |
| 235 | |
| 236 TEST_F(ListenSocketTest, ClientSend) { | |
| 237 tester_->TestClientSend(); | |
| 238 } | |
| 239 | |
| 240 TEST_F(ListenSocketTest, ClientSendLong) { | |
| 241 tester_->TestClientSendLong(); | |
| 242 } | |
| 243 | |
| 244 TEST_F(ListenSocketTest, ServerSend) { | |
| 245 tester_->TestServerSend(); | |
| 246 } | |
| 247 | |
| 248 } // namespace net | |
| OLD | NEW |