OLD | NEW |
| (Empty) |
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 "base/location.h" | |
9 #include "base/single_thread_task_runner.h" | |
10 #include "base/thread_task_runner_handle.h" | |
11 #include "testing/gtest/include/gtest/gtest.h" | |
12 | |
13 namespace { | |
14 const char kAsyncSocketIoTestString[] = "Hello, AsyncSocketIoHandler"; | |
15 const size_t kAsyncSocketIoTestStringLength = | |
16 arraysize(kAsyncSocketIoTestString); | |
17 | |
18 class TestSocketReader { | |
19 public: | |
20 // Set |number_of_reads_before_quit| to >0 when you expect a specific number | |
21 // of Read operations to complete. Once that number is reached, the current | |
22 // message loop will be Quit(). Set |number_of_reads_before_quit| to -1 if | |
23 // callbacks should not be counted. | |
24 TestSocketReader(base::CancelableSyncSocket* socket, | |
25 int number_of_reads_before_quit, | |
26 bool issue_reads_from_callback, | |
27 bool expect_eof) | |
28 : socket_(socket), buffer_(), | |
29 number_of_reads_before_quit_(number_of_reads_before_quit), | |
30 callbacks_received_(0), | |
31 issue_reads_from_callback_(issue_reads_from_callback), | |
32 expect_eof_(expect_eof) { | |
33 io_handler.Initialize(socket_->handle(), | |
34 base::Bind(&TestSocketReader::OnRead, | |
35 base::Unretained(this))); | |
36 } | |
37 ~TestSocketReader() {} | |
38 | |
39 bool IssueRead() { | |
40 return io_handler.Read(&buffer_[0], sizeof(buffer_)); | |
41 } | |
42 | |
43 const char* buffer() const { return &buffer_[0]; } | |
44 | |
45 int callbacks_received() const { return callbacks_received_; } | |
46 | |
47 private: | |
48 void OnRead(int bytes_read) { | |
49 if (!expect_eof_) { | |
50 EXPECT_GT(bytes_read, 0); | |
51 } else { | |
52 EXPECT_GE(bytes_read, 0); | |
53 } | |
54 ++callbacks_received_; | |
55 if (number_of_reads_before_quit_ == callbacks_received_) { | |
56 base::MessageLoop::current()->Quit(); | |
57 } else if (issue_reads_from_callback_) { | |
58 IssueRead(); | |
59 } | |
60 } | |
61 | |
62 base::AsyncSocketIoHandler io_handler; | |
63 base::CancelableSyncSocket* socket_; // Ownership lies outside the class. | |
64 char buffer_[kAsyncSocketIoTestStringLength]; | |
65 int number_of_reads_before_quit_; | |
66 int callbacks_received_; | |
67 bool issue_reads_from_callback_; | |
68 bool expect_eof_; | |
69 }; | |
70 | |
71 // Workaround to be able to use a base::Closure for sending data. | |
72 // Send() returns int but a closure must return void. | |
73 void SendData(base::CancelableSyncSocket* socket, | |
74 const void* buffer, | |
75 size_t length) { | |
76 socket->Send(buffer, length); | |
77 } | |
78 | |
79 } // end namespace. | |
80 | |
81 // Tests doing a pending read from a socket and use an IO handler to get | |
82 // notified of data. | |
83 TEST(AsyncSocketIoHandlerTest, AsynchronousReadWithMessageLoop) { | |
84 base::MessageLoopForIO loop; | |
85 | |
86 base::CancelableSyncSocket pair[2]; | |
87 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); | |
88 | |
89 TestSocketReader reader(&pair[0], 1, false, false); | |
90 EXPECT_TRUE(reader.IssueRead()); | |
91 | |
92 pair[1].Send(kAsyncSocketIoTestString, kAsyncSocketIoTestStringLength); | |
93 base::MessageLoop::current()->Run(); | |
94 EXPECT_EQ(strcmp(reader.buffer(), kAsyncSocketIoTestString), 0); | |
95 EXPECT_EQ(1, reader.callbacks_received()); | |
96 } | |
97 | |
98 // Tests doing a read from a socket when we know that there is data in the | |
99 // socket. Here we want to make sure that any async 'can read' notifications | |
100 // won't trip us off and that the synchronous case works as well. | |
101 TEST(AsyncSocketIoHandlerTest, SynchronousReadWithMessageLoop) { | |
102 base::MessageLoopForIO loop; | |
103 | |
104 base::CancelableSyncSocket pair[2]; | |
105 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); | |
106 | |
107 TestSocketReader reader(&pair[0], -1, false, false); | |
108 | |
109 pair[1].Send(kAsyncSocketIoTestString, kAsyncSocketIoTestStringLength); | |
110 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
111 FROM_HERE, base::MessageLoop::QuitClosure(), | |
112 base::TimeDelta::FromMilliseconds(100)); | |
113 base::MessageLoop::current()->Run(); | |
114 | |
115 EXPECT_TRUE(reader.IssueRead()); | |
116 EXPECT_EQ(strcmp(reader.buffer(), kAsyncSocketIoTestString), 0); | |
117 // We've now verified that the read happened synchronously, but it's not | |
118 // guaranteed that the callback has been issued since the callback will be | |
119 // called asynchronously even though the read may have been done. | |
120 // So we call RunUntilIdle() to allow any event notifications or APC's on | |
121 // Windows, to execute before checking the count of how many callbacks we've | |
122 // received. | |
123 base::MessageLoop::current()->RunUntilIdle(); | |
124 EXPECT_EQ(1, reader.callbacks_received()); | |
125 } | |
126 | |
127 // Calls Read() from within a callback to test that simple read "loops" work. | |
128 TEST(AsyncSocketIoHandlerTest, ReadFromCallback) { | |
129 base::MessageLoopForIO loop; | |
130 | |
131 base::CancelableSyncSocket pair[2]; | |
132 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); | |
133 | |
134 const int kReadOperationCount = 10; | |
135 TestSocketReader reader(&pair[0], kReadOperationCount, true, false); | |
136 EXPECT_TRUE(reader.IssueRead()); | |
137 | |
138 // Issue sends on an interval to satisfy the Read() requirements. | |
139 int64 milliseconds = 0; | |
140 for (int i = 0; i < kReadOperationCount; ++i) { | |
141 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
142 FROM_HERE, base::Bind(&SendData, &pair[1], kAsyncSocketIoTestString, | |
143 kAsyncSocketIoTestStringLength), | |
144 base::TimeDelta::FromMilliseconds(milliseconds)); | |
145 milliseconds += 10; | |
146 } | |
147 | |
148 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
149 FROM_HERE, base::MessageLoop::QuitClosure(), | |
150 base::TimeDelta::FromMilliseconds(100 + milliseconds)); | |
151 | |
152 base::MessageLoop::current()->Run(); | |
153 EXPECT_EQ(kReadOperationCount, reader.callbacks_received()); | |
154 } | |
155 | |
156 // Calls Read() then close other end, check that a correct callback is received. | |
157 TEST(AsyncSocketIoHandlerTest, ReadThenClose) { | |
158 base::MessageLoopForIO loop; | |
159 | |
160 base::CancelableSyncSocket pair[2]; | |
161 ASSERT_TRUE(base::CancelableSyncSocket::CreatePair(&pair[0], &pair[1])); | |
162 | |
163 const int kReadOperationCount = 1; | |
164 TestSocketReader reader(&pair[0], kReadOperationCount, false, true); | |
165 EXPECT_TRUE(reader.IssueRead()); | |
166 | |
167 pair[1].Close(); | |
168 | |
169 base::MessageLoop::current()->Run(); | |
170 EXPECT_EQ(kReadOperationCount, reader.callbacks_received()); | |
171 } | |
OLD | NEW |