Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1701)

Unified Diff: net/base/listen_socket_unittest.cc

Issue 9260: Change made by external contributor Ibrar Ahmed (ibrar.ahmad@gmail.com), revi... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/base/listen_socket_unittest.h ('k') | net/base/net_util.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/base/listen_socket_unittest.cc
===================================================================
--- net/base/listen_socket_unittest.cc (revision 5145)
+++ net/base/listen_socket_unittest.cc (working copy)
@@ -2,24 +2,307 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Tests ListenSocket.
-
#include "net/base/listen_socket_unittest.h"
-namespace {
+#include "base/platform_test.h"
+#include "net/base/net_util.h"
-class ListenSocketTest: public testing::Test {
-public:
+const int ListenSocketTester::kTestPort = 9999;
+
+static const int kReadBufSize = 1024;
+static const char* kHelloWorld = "HELLO, WORLD";
+static const int kMaxQueueSize = 20;
+static const char* kLoopback = "127.0.0.1";
+static const int kDefaultTimeoutMs = 5000;
+#if defined(OS_POSIX)
+static const char* kSemaphoreName = "chromium.listen_socket";
+#endif
+
+// millisecond sleep
+static void msleep(unsigned long milisec) {
+#if defined(OS_WIN)
+ Sleep(milisec);
+#elif defined(OS_POSIX)
+ struct timespec req = {0};
+ time_t sec = (int)(milisec / 1000);
+ milisec = milisec - (sec * 1000);
+ req.tv_sec = sec;
+ req.tv_nsec = milisec * 1000000L;
+ while (nanosleep(&req, &req) == -1)
+ continue;
+#endif
+}
+
+ListenSocket* ListenSocketTester::DoListen() {
+ return ListenSocket::Listen(kLoopback, kTestPort, this);
+}
+
+void ListenSocketTester::SetUp() {
+#if defined(OS_WIN)
+ InitializeCriticalSection(&lock_);
+ semaphore_ = CreateSemaphore(NULL, 0, kMaxQueueSize, NULL);
+ server_ = NULL;
+ net::EnsureWinsockInit();
+#elif defined(OS_POSIX)
+ ASSERT_EQ(0, pthread_mutex_init(&lock_, NULL ));
+ sem_unlink(kSemaphoreName);
+ semaphore_ = sem_open(kSemaphoreName, O_CREAT, 0, 0);
+ ASSERT_NE(SEM_FAILED, semaphore_);
+#endif
+ base::Thread::Options options;
+ options.message_loop_type = MessageLoop::TYPE_IO;
+ thread_.reset(new base::Thread("socketio_test"));
+ thread_->StartWithOptions(options);
+ loop_ = (MessageLoopForIO*)thread_->message_loop();
+
+ loop_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &ListenSocketTester::Listen));
+
+ // verify Listen succeeded
+ ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
+ ASSERT_FALSE(server_ == NULL);
+ ASSERT_EQ(ACTION_LISTEN, last_action_.type());
+
+ // verify the connect/accept and setup test_socket_
+ test_socket_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+ struct sockaddr_in client;
+ client.sin_family = AF_INET;
+ client.sin_addr.s_addr = inet_addr(kLoopback);
+ client.sin_port = htons(kTestPort);
+ int ret = connect(test_socket_,
+ reinterpret_cast<sockaddr*>(&client), sizeof(client));
+ ASSERT_NE(ret, SOCKET_ERROR);
+
+ net::SetNonBlocking(test_socket_);
+ ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
+ ASSERT_EQ(ACTION_ACCEPT, last_action_.type());
+}
+
+void ListenSocketTester::TearDown() {
+ // verify close
+#if defined(OS_WIN)
+ closesocket(test_socket_);
+#elif defined(OS_POSIX)
+ close(test_socket_);
+#endif
+ ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
+ ASSERT_EQ(ACTION_CLOSE, last_action_.type());
+
+ loop_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &ListenSocketTester::Shutdown));
+ ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
+ ASSERT_EQ(ACTION_SHUTDOWN, last_action_.type());
+
+#if defined(OS_WIN)
+ CloseHandle(semaphore_);
+ semaphore_ = 0;
+ DeleteCriticalSection(&lock_);
+#elif defined(OS_POSIX)
+ ASSERT_EQ(0, pthread_mutex_lock(&lock_));
+ semaphore_ = NULL;
+ ASSERT_EQ(0, pthread_mutex_unlock(&lock_));
+ ASSERT_EQ(0, sem_unlink(kSemaphoreName));
+ ASSERT_EQ(0, pthread_mutex_destroy(&lock_));
+#endif
+
+ thread_.reset();
+ loop_ = NULL;
+}
+
+void ListenSocketTester::ReportAction(const ListenSocketTestAction& action) {
+#if defined(OS_WIN)
+ EnterCriticalSection(&lock_);
+ queue_.push_back(action);
+ LeaveCriticalSection(&lock_);
+ ReleaseSemaphore(semaphore_, 1, NULL);
+#elif defined(OS_POSIX)
+ ASSERT_EQ(0, pthread_mutex_lock(&lock_));
+ queue_.push_back(action);
+ ASSERT_EQ(0, pthread_mutex_unlock(&lock_));
+ ASSERT_EQ(0, sem_post(semaphore_));
+#endif
+}
+
+bool ListenSocketTester::NextAction(int timeout) {
+#if defined(OS_WIN)
+ DWORD ret = ::WaitForSingleObject(semaphore_, timeout);
+ if (ret != WAIT_OBJECT_0)
+ return false;
+ EnterCriticalSection(&lock_);
+ if (queue_.size() == 0) {
+ LeaveCriticalSection(&lock_);
+ return false;
+ }
+ last_action_ = queue_.front();
+ queue_.pop_front();
+ LeaveCriticalSection(&lock_);
+ return true;
+#elif defined(OS_POSIX)
+ if (semaphore_ == SEM_FAILED)
+ return false;
+ while (true) {
+ int result = sem_trywait(semaphore_);
+ msleep(1); // 1ms sleep
+ timeout--;
+ if (timeout <= 0)
+ return false;
+ if (result == 0)
+ break;
+ }
+ pthread_mutex_lock(&lock_);
+ if (queue_.size() == 0) {
+ pthread_mutex_unlock(&lock_);
+ return false;
+ }
+ last_action_ = queue_.front();
+ queue_.pop_front();
+ pthread_mutex_unlock(&lock_);
+ return true;
+#endif
+}
+
+int ListenSocketTester::ClearTestSocket() {
+ char buf[kReadBufSize];
+ int len_ret = 0;
+ int time_out = 0;
+ do {
+ int len = recv(test_socket_, buf, kReadBufSize, 0);
+#if defined(OS_WIN)
+ if (len == SOCKET_ERROR) {
+ int err = WSAGetLastError();
+ if (err == WSAEWOULDBLOCK) {
+#elif defined(OS_POSIX)
+ if (len == SOCKET_ERROR) {
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+#endif
+ msleep(1);
+ time_out++;
+ if (time_out > 10)
+ break;
+ continue; // still trying
+ }
+ } else if (len == 0) {
+ // socket closed
+ break;
+ } else {
+ time_out = 0;
+ len_ret += len;
+ }
+ } while (true);
+ return len_ret;
+}
+
+void ListenSocketTester::Shutdown() {
+ connection_->Release();
+ connection_ = NULL;
+ server_->Release();
+ server_ = NULL;
+ ReportAction(ListenSocketTestAction(ACTION_SHUTDOWN));
+}
+
+void ListenSocketTester::Listen() {
+ server_ = DoListen();
+ if (server_) {
+ server_->AddRef();
+ ReportAction(ListenSocketTestAction(ACTION_LISTEN));
+ }
+}
+
+void ListenSocketTester::SendFromTester() {
+ connection_->Send(kHelloWorld);
+ ReportAction(ListenSocketTestAction(ACTION_SEND));
+}
+
+void ListenSocketTester::DidAccept(ListenSocket *server,
+ ListenSocket *connection) {
+ connection_ = connection;
+ connection_->AddRef();
+ ReportAction(ListenSocketTestAction(ACTION_ACCEPT));
+}
+
+void ListenSocketTester::DidRead(ListenSocket *connection,
+ const std::string& data) {
+ ReportAction(ListenSocketTestAction(ACTION_READ, data));
+}
+
+void ListenSocketTester::DidClose(ListenSocket *sock) {
+ ReportAction(ListenSocketTestAction(ACTION_CLOSE));
+}
+
+bool ListenSocketTester::Send(SOCKET sock, const std::string& str) {
+ int len = static_cast<int>(str.length());
+ int send_len = send(sock, str.data(), len, 0);
+ if (send_len == SOCKET_ERROR) {
+ LOG(ERROR) << "send failed: " << errno;
+ return false;
+ } else if (send_len != len) {
+ return false;
+ }
+ return true;
+}
+
+void ListenSocketTester::TestClientSend() {
+ ASSERT_TRUE(Send(test_socket_, kHelloWorld));
+ ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
+ ASSERT_EQ(ACTION_READ, last_action_.type());
+ ASSERT_EQ(last_action_.data(), kHelloWorld);
+}
+
+void ListenSocketTester::TestClientSendLong() {
+ int hello_len = strlen(kHelloWorld);
+ std::string long_string;
+ int long_len = 0;
+ for (int i = 0; i < 200; i++) {
+ long_string += kHelloWorld;
+ long_len += hello_len;
+ }
+ ASSERT_TRUE(Send(test_socket_, long_string));
+ int read_len = 0;
+ while (read_len < long_len) {
+ ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
+ ASSERT_EQ(ACTION_READ, last_action_.type());
+ std::string last_data = last_action_.data();
+ size_t len = last_data.length();
+ if (long_string.compare(read_len, len, last_data)) {
+ ASSERT_EQ(long_string.compare(read_len, len, last_data), 0);
+ }
+ read_len += static_cast<int>(last_data.length());
+ }
+ ASSERT_EQ(read_len, long_len);
+}
+
+void ListenSocketTester::TestServerSend() {
+ loop_->PostTask(FROM_HERE, NewRunnableMethod(
+ this, &ListenSocketTester::SendFromTester));
+ ASSERT_TRUE(NextAction(kDefaultTimeoutMs));
+ ASSERT_EQ(ACTION_SEND, last_action_.type());
+ // TODO(erikkay): Without this sleep, the recv seems to fail a small amount
+ // of the time. I could fix this by making the socket blocking, but then
+ // this test might hang in the case of errors. It would be nice to do
+ // something that felt more reliable here.
+ msleep(10); // sleep for 10ms
+ const int buf_len = 200;
+ char buf[buf_len+1];
+ int recv_len = recv(test_socket_, buf, buf_len, 0);
+ buf[recv_len] = 0;
+ ASSERT_STREQ(buf, kHelloWorld);
+}
+
+
+class ListenSocketTest: public PlatformTest {
+ public:
ListenSocketTest() {
tester_ = NULL;
}
virtual void SetUp() {
+ PlatformTest::SetUp();
tester_ = new ListenSocketTester();
tester_->SetUp();
}
virtual void TearDown() {
+ PlatformTest::TearDown();
tester_->TearDown();
tester_ = NULL;
}
@@ -27,8 +310,6 @@
scoped_refptr<ListenSocketTester> tester_;
};
-} // namespace
-
TEST_F(ListenSocketTest, ClientSend) {
tester_->TestClientSend();
}
« no previous file with comments | « net/base/listen_socket_unittest.h ('k') | net/base/net_util.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698