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