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