Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(252)

Side by Side Diff: google_apis/gcm/base/socket_stream_unittest.cc

Issue 23684017: [GCM] Initial work to set up directory structure and introduce socket integration (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 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 "google_apis/gcm/base/socket_stream.h"
6
7 #include "base/bind.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/run_loop.h"
10 #include "net/socket/socket_test_util.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12
13 namespace gcm {
14 namespace {
15
16 typedef std::vector<net::MockRead> ReadList;
17 typedef std::vector<net::MockWrite> WriteList;
18
19 const char kReadData[] = "read_data";
20 const char kReadData2[] = "read_alternate_data";
21 const char kWriteData[] = "write_data";
22
23 class GCMSocketStreamTest : public testing::Test {
24 public:
25 GCMSocketStreamTest();
26 virtual ~GCMSocketStreamTest();
27
28 // Build a socket with the expected reads and writes.
29 void BuildSocket(const ReadList& read_list, const WriteList& write_list);
30
31 // Pump the message loop until idle.
32 void PumpLoop();
33
34 // Simulates a google::protobuf::io::CodedInputStream read.
35 uint64 DoInputStreamRead(uint64 bytes,
36 bool set_limit,
37 const void** output_buffer);
38 // Simulates a google::protobuf::io::CodedOutputStream write.
39 uint64 DoOutputStreamWrite(uint64 bytes);
40
41 // Synchronous Refresh wrapper.
42 void WaitForData(int msg_size);
43
44 base::MessageLoop* message_loop() { return &message_loop_; };
45 net::DelayedSocketData* data_provider() { return data_provider_.get(); }
46 SocketInputStream* input_stream() { return socket_input_stream_.get(); }
47 SocketOutputStream* output_stream() { return socket_output_stream_.get(); }
48 net::StreamSocket* socket() { return socket_.get(); }
49
50 private:
51 void OpenConnection();
52 void ResetInputStream();
53 void ResetOutputStream();
54
55 void ConnectCallback(int result);
56
57 // SocketStreams and their data providers.
58 ReadList mock_reads_;
59 WriteList mock_writes_;
60 scoped_ptr<net::DelayedSocketData> data_provider_;
61 scoped_ptr<SocketInputStream> socket_input_stream_;
62 scoped_ptr<SocketOutputStream> socket_output_stream_;
63
64 // net:: components.
65 scoped_ptr<net::StreamSocket> socket_;
66 net::MockClientSocketFactory socket_factory_;
67 net::AddressList address_list_;
68
69 base::MessageLoopForIO message_loop_;
70 };
71
72 GCMSocketStreamTest::GCMSocketStreamTest() {
73 net::IPAddressNumber ip_number;
74 net::ParseIPLiteralToNumber("127.0.0.1", &ip_number);
75 address_list_ = net::AddressList::CreateFromIPAddress(ip_number, 5228);
76 }
77
78 GCMSocketStreamTest::~GCMSocketStreamTest() {}
79
80 void GCMSocketStreamTest::BuildSocket(const ReadList& read_list,
81 const WriteList& write_list) {
82 mock_reads_ = read_list;
83 mock_writes_ = write_list;
84 data_provider_.reset(
85 new net::DelayedSocketData(0,
86 &(mock_reads_[0]), mock_reads_.size(),
87 &(mock_writes_[0]), mock_writes_.size()));
88 socket_factory_.AddSocketDataProvider(data_provider_.get());
89 OpenConnection();
90 ResetInputStream();
91 ResetOutputStream();
92 }
93
94 void GCMSocketStreamTest::PumpLoop() {
95 base::RunLoop run_loop;
96 run_loop.RunUntilIdle();
97 }
98
99 uint64 GCMSocketStreamTest::DoInputStreamRead(uint64 bytes,
100 bool set_limit,
101 const void** output_buffer) {
102 uint64 total_bytes_read = 0;
103 const char* initial_buffer = NULL;
104 const char* buffer = NULL;
105 int size = 0;
106
107 do {
108 DCHECK(socket_input_stream_->state() == SocketInputStream::EMPTY ||
109 socket_input_stream_->state() == SocketInputStream::READY);
110 if (!socket_input_stream_->Next((const void **)&buffer, &size))
111 break;
112 total_bytes_read += size;
113 if (initial_buffer != NULL) // Verify the buffer doesn't skip data.
114 EXPECT_EQ(initial_buffer + total_bytes_read, buffer + size);
115 else
116 initial_buffer = buffer;
117 } while (total_bytes_read < bytes);
118
119 *output_buffer = (const void*)initial_buffer;
120
121 if (total_bytes_read > bytes) {
122 socket_input_stream_->BackUp(total_bytes_read - bytes);
123 total_bytes_read = bytes;
124 }
125
126 return total_bytes_read;
127 }
128
129 uint64 GCMSocketStreamTest::DoOutputStreamWrite(uint64 bytes) {
130 DCHECK_EQ(socket_output_stream_->state(), SocketOutputStream::EMPTY);
131 uint64 total_bytes_written = 0;
132 char* buffer = NULL;
133 int size = 0;
134 const char* write_src = kWriteData;
135
136 do {
137 if (!socket_output_stream_->Next((void **)&buffer, &size))
138 break;
139 uint64 bytes_to_write = ((uint64)size < bytes ? size : bytes);
140 memcpy(buffer, &write_src[total_bytes_written], bytes_to_write);
141 if (bytes_to_write < (uint64)size)
142 socket_output_stream_->BackUp(size - bytes_to_write);
143 total_bytes_written += bytes_to_write;
144 } while (total_bytes_written < bytes);
145
146 base::RunLoop run_loop;
147 socket_output_stream_->Flush(run_loop.QuitClosure());
148 run_loop.Run();
149
150 return total_bytes_written;
151 }
152
153 void ReadCallback(base::RunLoop* run_loop) {
154 run_loop->Quit();
155 }
156
157 void GCMSocketStreamTest::WaitForData(int msg_size) {
158 while (input_stream()->ByteCount() < msg_size) {
159 base::RunLoop run_loop;
160 input_stream()->Refresh(base::Bind(&ReadCallback,
161 base::Unretained(&run_loop)),
162 msg_size);
163 run_loop.Run();
164 if (input_stream()->state() == SocketInputStream::CLOSED)
165 return;
166 }
167 }
168
169 void GCMSocketStreamTest::OpenConnection() {
170 socket_ = socket_factory_.CreateTransportClientSocket(
171 address_list_, NULL, net::NetLog::Source());
172 socket_->Connect(
173 base::Bind(&GCMSocketStreamTest::ConnectCallback,
174 base::Unretained(this)));
175 PumpLoop();
176 }
177
178 void GCMSocketStreamTest::ConnectCallback(int result) {}
179
180 void GCMSocketStreamTest::ResetInputStream() {
181 DCHECK(socket_.get());
182 socket_input_stream_.reset(
183 new SocketInputStream(socket_.get()));
184 }
185
186 void GCMSocketStreamTest::ResetOutputStream() {
187 DCHECK(socket_.get());
188 socket_output_stream_.reset(new SocketOutputStream(socket_.get()));
189 }
190
191 // A read where all data is already available.
192 TEST_F(GCMSocketStreamTest, ReadDataSync) {
193 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS, kReadData)),
194 WriteList());
195
196 const void* output = NULL;
197 WaitForData(strlen(kReadData));
198 ASSERT_EQ(strlen(kReadData),
199 DoInputStreamRead(strlen(kReadData), false, &output));
200 ASSERT_EQ(std::string(kReadData),
201 std::string((const char*)output, strlen(kReadData)));
202 }
203
204 // A read that comes in two parts.
205 TEST_F(GCMSocketStreamTest, ReadPartialDataSync) {
206 size_t first_read_len = strlen(kReadData)/2;
207 size_t second_read_len = strlen(kReadData) - first_read_len;
208 ReadList read_list;
209 read_list.push_back(
210 net::MockRead(net::SYNCHRONOUS,
211 kReadData, first_read_len));
212 read_list.push_back(
213 net::MockRead(net::SYNCHRONOUS,
214 &kReadData[first_read_len], second_read_len));
215 BuildSocket(read_list, WriteList());
216
217 const void* output = NULL;
218 WaitForData(strlen(kReadData));
219 ASSERT_EQ(strlen(kReadData),
220 DoInputStreamRead(strlen(kReadData), false, &output));
221 ASSERT_EQ(std::string(kReadData),
222 std::string((const char*)output, strlen(kReadData)));
223 }
224
225 // A read where no data is available at first (IO_PENDING will be returned).
226 TEST_F(GCMSocketStreamTest, ReadAsync) {
227 size_t first_read_len = strlen(kReadData)/2;
228 size_t second_read_len = strlen(kReadData) - first_read_len;
229 ReadList read_list;
230 read_list.push_back(
231 net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING));
232 read_list.push_back(
233 net::MockRead(net::ASYNC, kReadData, first_read_len));
234 read_list.push_back(
235 net::MockRead(net::ASYNC, &kReadData[first_read_len], second_read_len));
236 BuildSocket(read_list, WriteList());
237
238 const void* output = NULL;
239 base::MessageLoop::current()->PostTask(
240 FROM_HERE,
241 base::Bind(&net::DelayedSocketData::ForceNextRead,
242 base::Unretained(data_provider())));
243 WaitForData(strlen(kReadData));
244 ASSERT_EQ(strlen(kReadData),
245 DoInputStreamRead(strlen(kReadData), false, &output));
246 ASSERT_EQ(std::string(kReadData),
247 std::string((const char*)output, strlen(kReadData)));
248 }
249
250 // Simulate two packets arriving at once. Read them in two separate calls.
251 TEST_F(GCMSocketStreamTest, TwoReadsAtOnce) {
252 std::string long_data = std::string(kReadData) + std::string(kReadData2);
253 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS, long_data.c_str())),
254 WriteList());
255 const void* output = NULL;
256
257 WaitForData(strlen(kReadData));
258 ASSERT_EQ(strlen(kReadData),
259 DoInputStreamRead(strlen(kReadData), false, &output));
260 ASSERT_EQ(std::string(kReadData, strlen(kReadData)),
261 std::string((const char*)output, strlen(kReadData)));
262
263 WaitForData(strlen(kReadData2));
264 ASSERT_EQ(strlen(kReadData2),
265 DoInputStreamRead(strlen(kReadData2), false, &output));
266 ASSERT_EQ(std::string(kReadData2, strlen(kReadData)),
267 std::string((const char*)output, strlen(kReadData)));
268 }
269
270 // Simulate two packets arriving at once. Read them in two calls separated
271 // by a Rebuild.
272 TEST_F(GCMSocketStreamTest, TwoReadsAtOnceWithRebuild) {
273 std::string long_data = std::string(kReadData) + std::string(kReadData2);
274 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS, long_data.c_str())),
275 WriteList());
276
277 const void* output = NULL;
278 WaitForData(strlen(kReadData));
279 ASSERT_EQ(strlen(kReadData),
280 DoInputStreamRead(strlen(kReadData), false, &output));
281 ASSERT_EQ(std::string(kReadData, strlen(kReadData)),
282 std::string((const char*)output, strlen(kReadData)));
283
284 input_stream()->RebuildBuffer();
285 WaitForData(strlen(kReadData2));
286 ASSERT_EQ(strlen(kReadData2),
287 DoInputStreamRead(strlen(kReadData2), false, &output));
288 ASSERT_EQ(std::string(kReadData2, strlen(kReadData2)),
289 std::string((const char*)output, strlen(kReadData2)));
290 }
291
292 // Simulate a read that is aborted.
293 TEST_F(GCMSocketStreamTest, ReadError) {
294 int result = net::ERR_ABORTED;
295 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS, result)),
296 WriteList());
297
298 WaitForData(strlen(kReadData));
299 ASSERT_EQ(SocketInputStream::CLOSED, input_stream()->state());
300 ASSERT_EQ(result, input_stream()->last_error());
301 }
302
303 // Simulate a read after the connection is closed.
304 TEST_F(GCMSocketStreamTest, ReadDisconnected) {
305 BuildSocket(ReadList(), WriteList());
306 socket()->Disconnect();
307 WaitForData(strlen(kReadData));
308 ASSERT_EQ(SocketInputStream::CLOSED, input_stream()->state());
309 ASSERT_EQ(net::ERR_CONNECTION_CLOSED, input_stream()->last_error());
310 }
311
312 // Write a full message in one go.
313 TEST_F(GCMSocketStreamTest, WriteFull) {
314 BuildSocket(ReadList(),
315 WriteList(1, net::MockWrite(net::SYNCHRONOUS, kWriteData)));
316 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
317 }
318
319 // Write a message in two go's.
320 TEST_F(GCMSocketStreamTest, WritePartial) {
321 std::string full_data = std::string(kWriteData);
322 std::string part1 = full_data.substr(0, full_data.length()/2);
323 std::string part2 = full_data.substr(full_data.length()/2);
324 WriteList write_list;
325 write_list.push_back(net::MockWrite(net::SYNCHRONOUS, part1.c_str()));
326 write_list.push_back(net::MockWrite(net::SYNCHRONOUS, part2.c_str()));
327 BuildSocket(ReadList(), write_list);
328 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
329 }
330
331 // Write a message completely asynchronously (returns IO_PENDING before
332 // finishing the write in two go's).
333 TEST_F(GCMSocketStreamTest, WriteNone) {
334 std::string full_data = std::string(kWriteData);
335 std::string part1 = full_data.substr(0, full_data.length()/2);
336 std::string part2 = full_data.substr(full_data.length()/2);
337 WriteList write_list;
338 write_list.push_back(net::MockWrite(net::ASYNC, part1.c_str()));
339 write_list.push_back(net::MockWrite(net::ASYNC, part2.c_str()));
340 BuildSocket(ReadList(), write_list);
341 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
342 }
343
344 // Write a message then read a message.
345 TEST_F(GCMSocketStreamTest, WriteThenRead) {
346 BuildSocket(ReadList(1, net::MockRead(kReadData)),
347 WriteList(1, net::MockWrite(kWriteData)));
348
349 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
350
351 const void* output = NULL;
352 WaitForData(strlen(kReadData));
353 ASSERT_EQ(strlen(kReadData),
354 DoInputStreamRead(strlen(kReadData), false, &output));
355 ASSERT_EQ(std::string(kReadData),
356 std::string((const char*)output, strlen(kReadData)));
357 }
358
359 // Read a message then write a message.
360 TEST_F(GCMSocketStreamTest, ReadThenWrite) {
361 BuildSocket(ReadList(1, net::MockRead(kReadData)),
362 WriteList(1, net::MockWrite(kWriteData)));
363
364 const void* output = NULL;
365 WaitForData(strlen(kReadData));
366 ASSERT_EQ(strlen(kReadData),
367 DoInputStreamRead(strlen(kReadData), false, &output));
368 ASSERT_EQ(std::string(kReadData),
369 std::string((const char*)output, strlen(kReadData)));
370
371 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
372 }
373
374 // Simulate a write that gets aborted.
375 TEST_F(GCMSocketStreamTest, WriteError) {
376 int result = net::ERR_ABORTED;
377 BuildSocket(ReadList(),
378 WriteList(1, net::MockWrite(net::SYNCHRONOUS, result)));
379 DoOutputStreamWrite(strlen(kWriteData));
380 ASSERT_EQ(SocketOutputStream::CLOSED, output_stream()->state());
381 ASSERT_EQ(result, output_stream()->last_error());
382 }
383
384 // Simulate a write after the connection is closed.
385 TEST_F(GCMSocketStreamTest, WriteDisconnected) {
386 BuildSocket(ReadList(), WriteList());
387 socket()->Disconnect();
388 DoOutputStreamWrite(strlen(kWriteData));
389 ASSERT_EQ(SocketOutputStream::CLOSED, output_stream()->state());
390 ASSERT_EQ(net::ERR_CONNECTION_CLOSED, output_stream()->last_error());
391 }
392
393 } // namespace
394 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698