1 // Copyright 2013 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 "base/async_socket_io_handler.h" 6 7 #include "base/bind.h" 8 #include "testing/gtest/include/gtest/gtest.h" 9 10 namespace { 11 const char kAsyncSocketIoTestString[] = "Hello, AsyncSocketIoHandler"; 12 const size_t kAsyncSocketIoTestStringLength = 13 arraysize(kAsyncSocketIoTestString); 14 15 class TestSocketReader { 16 public: 17 // Set |number_of_reads_before_quit| to >0 when you expect a specific number 18 // of Read operations to complete. Once that number is reached, the current 19 // message loop will be Quit(). Set |number_of_reads_before_quit| to -1 if 20 // callbacks should not be counted. 21 TestSocketReader(base::CancelableSyncSocket* socket, 22 int number_of_reads_before_quit, 23 bool issue_reads_from_callback, 24 bool expect_eof) 25 : socket_(socket), buffer_(), 26 number_of_reads_before_quit_(number_of_reads_before_quit), 27 callbacks_received_(0), 28 issue_reads_from_callback_(issue_reads_from_callback), 29 expect_eof_(expect_eof) { 30 io_handler.Initialize(socket_->handle(), 31 base::Bind(&TestSocketReader::OnRead, 32 base::Unretained(this))); 33 } 34 ~TestSocketReader() {} 35 36 bool IssueRead() { 37 return io_handler.Read(&buffer_[0], sizeof(buffer_)); 38 } 39 40 const char* buffer() const { return &buffer_[0]; } 41 42 int callbacks_received() const { return callbacks_received_; } 43 44 private: 45 void OnRead(int bytes_read) { 46 if (!expect_eof_) { 47 EXPECT_GT(bytes_read, 0); 48 } else { 49 EXPECT_GE(bytes_read, 0); 50 } 51 ++callbacks_received_; 52 if (number_of_reads_before_quit_ == callbacks_received_) { 53 base::MessageLoop::current()->Quit(); 54 } else if (issue_reads_from_callback_) { 55 IssueRead(); 56 } 57 } 58 59 base::AsyncSocketIoHandler io_handler; 60 base::CancelableSyncSocket* socket_; // Ownership lies outside the class. 61 char buffer_[kAsyncSocketIoTestStringLength]; 62 int number_of_reads_before_quit_; 63 int callbacks_received_; 64 bool issue_reads_from_callback_; 65 bool expect_eof_; 66 }; 67 68 // Workaround to be able to use a base::Closure for sending data. 69 // Send() returns int but a closure must return void. 70 void SendData(base::CancelableSyncSocket* socket, 71 const void* buffer, 72 size_t length) { 73 socket->Send(buffer, length); 74 } 75 76 } // end namespace. 77 78 // Tests doing a pending read from a socket and use an IO handler to get 79 // notified of data. 80 TEST(AsyncSocketIoHandlerTest, AsynchronousReadWithMessageLoop) { 81 base::MessageLoopForIO loop; 82 83 base::CancelableSyncSocket pair[2]; 84 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); 85 86 TestSocketReader reader(&pair[0], 1, false, false); 87 EXPECT_TRUE(reader.IssueRead()); 88 89 pair[1].Send(kAsyncSocketIoTestString, kAsyncSocketIoTestStringLength); 90 base::MessageLoop::current()->Run(); 91 EXPECT_EQ(strcmp(reader.buffer(), kAsyncSocketIoTestString), 0); 92 EXPECT_EQ(1, reader.callbacks_received()); 93 } 94 95 // Tests doing a read from a socket when we know that there is data in the 96 // socket. Here we want to make sure that any async 'can read' notifications 97 // won't trip us off and that the synchronous case works as well. 98 TEST(AsyncSocketIoHandlerTest, SynchronousReadWithMessageLoop) { 99 base::MessageLoopForIO loop; 100 101 base::CancelableSyncSocket pair[2]; 102 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); 103 104 TestSocketReader reader(&pair[0], -1, false, false); 105 106 pair[1].Send(kAsyncSocketIoTestString, kAsyncSocketIoTestStringLength); 107 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 108 base::MessageLoop::QuitClosure(), 109 base::TimeDelta::FromMilliseconds(100)); 110 base::MessageLoop::current()->Run(); 111 112 EXPECT_TRUE(reader.IssueRead()); 113 EXPECT_EQ(strcmp(reader.buffer(), kAsyncSocketIoTestString), 0); 114 // We've now verified that the read happened synchronously, but it's not 115 // guaranteed that the callback has been issued since the callback will be 116 // called asynchronously even though the read may have been done. 117 // So we call RunUntilIdle() to allow any event notifications or APC's on 118 // Windows, to execute before checking the count of how many callbacks we've 119 // received. 120 base::MessageLoop::current()->RunUntilIdle(); 121 EXPECT_EQ(1, reader.callbacks_received()); 122 } 123 124 // Calls Read() from within a callback to test that simple read "loops" work. 125 TEST(AsyncSocketIoHandlerTest, ReadFromCallback) { 126 base::MessageLoopForIO loop; 127 128 base::CancelableSyncSocket pair[2]; 129 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); 130 131 const int kReadOperationCount = 10; 132 TestSocketReader reader(&pair[0], kReadOperationCount, true, false); 133 EXPECT_TRUE(reader.IssueRead()); 134 135 // Issue sends on an interval to satisfy the Read() requirements. 136 int64 milliseconds = 0; 137 for (int i = 0; i < kReadOperationCount; ++i) { 138 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 139 base::Bind(&SendData, &pair[1], kAsyncSocketIoTestString, 140 kAsyncSocketIoTestStringLength), 141 base::TimeDelta::FromMilliseconds(milliseconds)); 142 milliseconds += 10; 143 } 144 145 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 146 base::MessageLoop::QuitClosure(), 147 base::TimeDelta::FromMilliseconds(100 + milliseconds)); 148 149 base::MessageLoop::current()->Run(); 150 EXPECT_EQ(kReadOperationCount, reader.callbacks_received()); 151 } 152 153 // Calls Read() then close other end, check that a correct callback is received. 154 TEST(AsyncSocketIoHandlerTest, ReadThenClose) { 155 base::MessageLoopForIO loop; 156 157 base::CancelableSyncSocket pair[2]; 158 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); 159 160 const int kReadOperationCount = 1; 161 TestSocketReader reader(&pair[0], kReadOperationCount, false, true); 162 EXPECT_TRUE(reader.IssueRead()); 163 164 pair[1].Close(); 165 166 base::MessageLoop::current()->Run(); 167 EXPECT_EQ(kReadOperationCount, reader.callbacks_received()); 168 } 169