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
10namespace {
11const char kAsyncSocketIoTestString[] = "Hello, AsyncSocketIoHandler";
12const size_t kAsyncSocketIoTestStringLength =
13    arraysize(kAsyncSocketIoTestString);
14
15class 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.
70void 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.
80TEST(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.
98TEST(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.
125TEST(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.
154TEST(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