• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
TestSocketReader(base::CancelableSyncSocket * socket,int number_of_reads_before_quit,bool issue_reads_from_callback,bool expect_eof)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   }
~TestSocketReader()34   ~TestSocketReader() {}
35 
IssueRead()36   bool IssueRead() {
37     return io_handler.Read(&buffer_[0], sizeof(buffer_));
38   }
39 
buffer() const40   const char* buffer() const { return &buffer_[0]; }
41 
callbacks_received() const42   int callbacks_received() const { return callbacks_received_; }
43 
44  private:
OnRead(int bytes_read)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.
SendData(base::CancelableSyncSocket * socket,const void * buffer,size_t length)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.
TEST(AsyncSocketIoHandlerTest,AsynchronousReadWithMessageLoop)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.
TEST(AsyncSocketIoHandlerTest,SynchronousReadWithMessageLoop)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.
TEST(AsyncSocketIoHandlerTest,ReadFromCallback)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.
TEST(AsyncSocketIoHandlerTest,ReadThenClose)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