Home | History | Annotate | Download | only in base
      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