13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "base/async_socket_io_handler.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAsyncSocketIoTestString[] = "Hello, AsyncSocketIoHandler"; 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kAsyncSocketIoTestStringLength = 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(kAsyncSocketIoTestString); 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestSocketReader { 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set |number_of_reads_before_quit| to >0 when you expect a specific number 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of Read operations to complete. Once that number is reached, the current 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message loop will be Quit(). Set |number_of_reads_before_quit| to -1 if 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // callbacks should not be counted. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TestSocketReader(base::CancelableSyncSocket* socket, 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int number_of_reads_before_quit, 232385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch bool issue_reads_from_callback, 242385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch bool expect_eof) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : socket_(socket), buffer_(), 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) number_of_reads_before_quit_(number_of_reads_before_quit), 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callbacks_received_(0), 282385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch issue_reads_from_callback_(issue_reads_from_callback), 292385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch expect_eof_(expect_eof) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) io_handler.Initialize(socket_->handle(), 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&TestSocketReader::OnRead, 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~TestSocketReader() {} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IssueRead() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return io_handler.Read(&buffer_[0], sizeof(buffer_)); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* buffer() const { return &buffer_[0]; } 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int callbacks_received() const { return callbacks_received_; } 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnRead(int bytes_read) { 462385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch if (!expect_eof_) { 472385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch EXPECT_GT(bytes_read, 0); 482385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } else { 492385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch EXPECT_GE(bytes_read, 0); 502385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++callbacks_received_; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (number_of_reads_before_quit_ == callbacks_received_) { 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->Quit(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (issue_reads_from_callback_) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IssueRead(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::AsyncSocketIoHandler io_handler; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CancelableSyncSocket* socket_; // Ownership lies outside the class. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buffer_[kAsyncSocketIoTestStringLength]; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int number_of_reads_before_quit_; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int callbacks_received_; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool issue_reads_from_callback_; 652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch bool expect_eof_; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Workaround to be able to use a base::Closure for sending data. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Send() returns int but a closure must return void. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SendData(base::CancelableSyncSocket* socket, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* buffer, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t length) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket->Send(buffer, length); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // end namespace. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests doing a pending read from a socket and use an IO handler to get 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notified of data. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(AsyncSocketIoHandlerTest, AsynchronousReadWithMessageLoop) { 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForIO loop; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CancelableSyncSocket pair[2]; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 862385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch TestSocketReader reader(&pair[0], 1, false, false); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(reader.IssueRead()); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pair[1].Send(kAsyncSocketIoTestString, kAsyncSocketIoTestStringLength); 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->Run(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(strcmp(reader.buffer(), kAsyncSocketIoTestString), 0); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, reader.callbacks_received()); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tests doing a read from a socket when we know that there is data in the 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// socket. Here we want to make sure that any async 'can read' notifications 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// won't trip us off and that the synchronous case works as well. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(AsyncSocketIoHandlerTest, SynchronousReadWithMessageLoop) { 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForIO loop; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CancelableSyncSocket pair[2]; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch TestSocketReader reader(&pair[0], -1, false, false); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pair[1].Send(kAsyncSocketIoTestString, kAsyncSocketIoTestStringLength); 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::QuitClosure(), 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(100)); 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->Run(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(reader.IssueRead()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(strcmp(reader.buffer(), kAsyncSocketIoTestString), 0); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We've now verified that the read happened synchronously, but it's not 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // guaranteed that the callback has been issued since the callback will be 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // called asynchronously even though the read may have been done. 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // So we call RunUntilIdle() to allow any event notifications or APC's on 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Windows, to execute before checking the count of how many callbacks we've 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // received. 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(1, reader.callbacks_received()); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Calls Read() from within a callback to test that simple read "loops" work. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(AsyncSocketIoHandlerTest, ReadFromCallback) { 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoopForIO loop; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::CancelableSyncSocket pair[2]; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int kReadOperationCount = 10; 1322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch TestSocketReader reader(&pair[0], kReadOperationCount, true, false); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_TRUE(reader.IssueRead()); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Issue sends on an interval to satisfy the Read() requirements. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 milliseconds = 0; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < kReadOperationCount; ++i) { 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SendData, &pair[1], kAsyncSocketIoTestString, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAsyncSocketIoTestStringLength), 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(milliseconds)); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) milliseconds += 10; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask(FROM_HERE, 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::QuitClosure(), 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(100 + milliseconds)); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::MessageLoop::current()->Run(); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EXPECT_EQ(kReadOperationCount, reader.callbacks_received()); 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1522385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 1532385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch// Calls Read() then close other end, check that a correct callback is received. 1542385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochTEST(AsyncSocketIoHandlerTest, ReadThenClose) { 1552385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch base::MessageLoopForIO loop; 1562385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 1572385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch base::CancelableSyncSocket pair[2]; 1582385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); 1592385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 1602385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch const int kReadOperationCount = 1; 1612385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch TestSocketReader reader(&pair[0], kReadOperationCount, false, true); 1622385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch EXPECT_TRUE(reader.IssueRead()); 1632385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 1642385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch pair[1].Close(); 1652385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch 1662385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch base::MessageLoop::current()->Run(); 1672385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch EXPECT_EQ(kReadOperationCount, reader.callbacks_received()); 1682385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch} 169