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

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: Self review Created 7 years, 3 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 "base/test/test_timeouts.h"
11 #include "google_apis/gcm/base/socket_stream_test_data_provider.h"
12 #include "net/socket/socket_test_util.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14
15 namespace gcm {
16 namespace {
17
18 const char kReadData[] = "read_data";
19 const char kReadData2[] = "read_alternate_data";
20 const char kWriteData[] = "write_data";
21
22 class GCMSocketStreamTest : public testing::Test {
23 public:
24 GCMSocketStreamTest();
25 virtual ~GCMSocketStreamTest();
26
27 void PumpLoop();
28
29 void OpenConnection();
30 void ResetInputStream();
31 void ResetOutputStream();
32
33 base::MessageLoop* message_loop() { return &message_loop_; };
34 SocketStreamTestDataProvider* data_provider() { return &data_provider_; }
35 SocketInputStream* input_stream() { return socket_input_stream_.get(); }
36 SocketOutputStream* output_stream() { return socket_output_stream_.get(); }
37 net::StreamSocket* socket() { return socket_.get(); }
38
39 // Simulates a google::protobuf::io::CodedInputStream read.
40 uint64 DoInputStreamRead(uint64 bytes,
41 bool set_limit,
42 const void** output_buffer);
43 // Simulates a google::protobuf::io::CodedOutputStream write.
44 uint64 DoOutputStreamWrite(uint64 bytes);
45
46 private:
47 void ConnectCallback(int result);
48
49 // SocketStreams and their data provider.
50 SocketStreamTestDataProvider data_provider_;
51 scoped_ptr<SocketInputStream> socket_input_stream_;
52 scoped_ptr<SocketOutputStream> socket_output_stream_;
53
54 // net:: components.
55 scoped_ptr<net::StreamSocket> socket_;
56 net::MockClientSocketFactory socket_factory_;
57 net::AddressList address_list_;
58
59 base::MessageLoopForIO message_loop_;
60 };
61
62 GCMSocketStreamTest::GCMSocketStreamTest() {
63 net::IPAddressNumber ip_number;
64 net::ParseIPLiteralToNumber("127.0.0.1", &ip_number);
65 address_list_ = net::AddressList::CreateFromIPAddress(ip_number, 5228);
66
67 socket_factory_.AddSocketDataProvider(&data_provider_);
68
69 OpenConnection();
70 ResetInputStream();
71 ResetOutputStream();
72 }
73
74 GCMSocketStreamTest::~GCMSocketStreamTest() {}
75
76 void GCMSocketStreamTest::PumpLoop() {
77 base::RunLoop run_loop;
78 run_loop.RunUntilIdle();
79 }
80
81 void GCMSocketStreamTest::OpenConnection() {
82 socket_ = socket_factory_.CreateTransportClientSocket(
83 address_list_, NULL, net::NetLog::Source());
84 socket_->Connect(
85 base::Bind(&GCMSocketStreamTest::ConnectCallback,
86 base::Unretained(this)));
87 PumpLoop();
88 }
89
90 void GCMSocketStreamTest::ConnectCallback(int result) {}
91
92 void GCMSocketStreamTest::ResetInputStream() {
93 DCHECK(socket_.get());
94 socket_input_stream_.reset(
95 new SocketInputStream(TestTimeouts::tiny_timeout(),
96 socket_.get()));
97 }
98
99 void GCMSocketStreamTest::ResetOutputStream() {
100 DCHECK(socket_.get());
101 socket_output_stream_.reset(new SocketOutputStream(socket_.get()));
102 }
103
104 uint64 GCMSocketStreamTest::DoInputStreamRead(uint64 bytes,
105 bool set_limit,
106 const void** output_buffer) {
107 uint64 total_bytes_read = 0;
108 const char* initial_buffer = NULL;
109 const char* buffer = NULL;
110 int size = 0;
111
112 if (set_limit) {
113 socket_input_stream_->SetLimit(socket_input_stream_->GetCurrentPosition() +
114 bytes);
115 }
116
117 do {
118 DCHECK(socket_input_stream_->state() == SocketInputStream::EMPTY ||
119 socket_input_stream_->state() == SocketInputStream::READY);
120 if (!socket_input_stream_->Next((const void **)&buffer, &size))
121 break;
122 total_bytes_read += size;
123 if (initial_buffer != NULL) // Verify the buffer doesn't skip data.
124 EXPECT_EQ(initial_buffer + total_bytes_read, buffer + size);
125 else
126 initial_buffer = buffer;
127 } while (total_bytes_read < bytes);
128
129 *output_buffer = (const void*)initial_buffer;
130
131 if (total_bytes_read > bytes) {
132 socket_input_stream_->BackUp(total_bytes_read - bytes);
133 total_bytes_read = bytes;
134 }
135
136 return total_bytes_read;
137 }
138
139 uint64 GCMSocketStreamTest::DoOutputStreamWrite(uint64 bytes) {
140 DCHECK_EQ(socket_output_stream_->state(), SocketOutputStream::EMPTY);
141 uint64 total_bytes_written = 0;
142 char* buffer = NULL;
143 int size = 0;
144 const char* write_src = kWriteData;
145
146 do {
147 if (!socket_output_stream_->Next((void **)&buffer, &size))
148 break;
149 uint64 bytes_to_write = ((uint64)size < bytes ? size : bytes);
150 memcpy(buffer, &write_src[total_bytes_written], bytes_to_write);
151 if (bytes_to_write < (uint64)size)
152 socket_output_stream_->BackUp(size - bytes_to_write);
153 total_bytes_written += bytes_to_write;
154 } while (total_bytes_written < bytes);
155
156 base::RunLoop run_loop;
157 socket_output_stream_->Flush(run_loop.QuitClosure());
158 run_loop.Run();
159
160 return total_bytes_written;
161 }
162
163 // A read where all data is already available.
164 TEST_F(GCMSocketStreamTest, ReadPendingData) {
165 data_provider()->AddRead(net::MockRead(kReadData));
166 const void* output = NULL;
167 ASSERT_EQ(strlen(kReadData),
168 DoInputStreamRead(strlen(kReadData), false, &output));
169 ASSERT_EQ(std::string(kReadData),
170 std::string((const char*)output, strlen(kReadData)));
171 }
172
173 // A read that comes in two parts.
174 TEST_F(GCMSocketStreamTest, ReadPartialData) {
175 size_t first_read_len = strlen(kReadData)/2;
176 size_t second_read_len = strlen(kReadData) - first_read_len;
177 data_provider()->AddRead(
178 net::MockRead(net::ASYNC, kReadData, first_read_len));
179 data_provider()->AddRead(
180 net::MockRead(net::ASYNC, &kReadData[first_read_len], second_read_len));
181 const void* output = NULL;
182 ASSERT_EQ(strlen(kReadData),
183 DoInputStreamRead(strlen(kReadData), false, &output));
184 ASSERT_EQ(std::string(kReadData),
185 std::string((const char*)output, strlen(kReadData)));
186 }
187
188 // A read where no data is available at first (IO_PENDING will be returned).
189 TEST_F(GCMSocketStreamTest, ReadNoData) {
190 size_t first_read_len = strlen(kReadData)/2;
191 size_t second_read_len = strlen(kReadData) - first_read_len;
192 message_loop()->PostTask(
193 FROM_HERE,
194 base::Bind(&SocketStreamTestDataProvider::AddRead,
195 base::Unretained(data_provider()),
196 net::MockRead(net::ASYNC, kReadData, first_read_len)));
197 message_loop()->PostTask(
198 FROM_HERE,
199 base::Bind(&SocketStreamTestDataProvider::AddRead,
200 base::Unretained(data_provider()),
201 net::MockRead(net::ASYNC,
202 &kReadData[first_read_len],
203 second_read_len)));
204 const void* output = NULL;
205 ASSERT_EQ(strlen(kReadData),
206 DoInputStreamRead(strlen(kReadData), false, &output));
207 ASSERT_EQ(std::string(kReadData),
208 std::string((const char*)output, strlen(kReadData)));
209 }
210
211 // A read where a second message arrives at the same time. The second message
212 // is then read.
213 TEST_F(GCMSocketStreamTest, TwoReadsAtOnce) {
214 std::string long_data = std::string(kReadData) + std::string(kReadData2);
215 data_provider()->AddRead(net::MockRead(long_data.c_str()));
216 const void* output = NULL;
217 ASSERT_EQ(strlen(kReadData),
218 DoInputStreamRead(strlen(kReadData), false, &output));
219 ASSERT_EQ(std::string(kReadData, strlen(kReadData)),
220 std::string((const char*)output, strlen(kReadData)));
221 ASSERT_EQ(strlen(kReadData2),
222 DoInputStreamRead(strlen(kReadData2), false, &output));
223 ASSERT_EQ(std::string(kReadData2, strlen(kReadData)),
224 std::string((const char*)output, strlen(kReadData)));
225 }
226
227 // A read where a second message arrives at the same time. The input stream
228 // is reset before the second message is read.
229 TEST_F(GCMSocketStreamTest, TwoReadsAtOnceWithReset) {
230 std::string long_data = std::string(kReadData) + std::string(kReadData2);
231 data_provider()->AddRead(net::MockRead(long_data.c_str()));
232 const void* output = NULL;
233 ASSERT_EQ(strlen(kReadData),
234 DoInputStreamRead(strlen(kReadData), false, &output));
235 ASSERT_EQ(std::string(kReadData, strlen(kReadData)),
236 std::string((const char*)output, strlen(kReadData)));
237 input_stream()->Reset();
238 ASSERT_EQ(strlen(kReadData2),
239 DoInputStreamRead(strlen(kReadData2), false, &output));
240 ASSERT_EQ(std::string(kReadData2, strlen(kReadData2)),
241 std::string((const char*)output, strlen(kReadData2)));
242 }
243
244 // A read where a second message arrives at the same time. The second message
245 // is then read. A limit is set on each read.
246 TEST_F(GCMSocketStreamTest, TwoReadsAtOnceWithLimit) {
247 std::string long_data = std::string(kReadData) + std::string(kReadData2);
248 data_provider()->AddRead(net::MockRead(net::ASYNC,
249 long_data.c_str(),
250 long_data.size()));
251 const void* output = NULL;
252 ASSERT_EQ(strlen(kReadData),
253 DoInputStreamRead(strlen(kReadData), true, &output));
254 ASSERT_EQ(std::string(kReadData, strlen(kReadData)),
255 std::string((const char*)output, strlen(kReadData)));
256 ASSERT_EQ(strlen(kReadData2),
257 DoInputStreamRead(strlen(kReadData2), true, &output));
258 ASSERT_EQ(std::string(kReadData2, strlen(kReadData2)),
259 std::string((const char*)output, strlen(kReadData2)));
260 }
261
262 // A read where a second message arrives at the same time, but a reset happens
263 // between reads. A limit is set on each read.
264 TEST_F(GCMSocketStreamTest, TwoReadsAtOnceWithLimitAndReset) {
265 std::string long_data = std::string(kReadData) + std::string(kReadData2);
266 data_provider()->AddRead(net::MockRead(long_data.c_str()));
267 const void* output = NULL;
268 ASSERT_EQ(strlen(kReadData),
269 DoInputStreamRead(strlen(kReadData), true, &output));
270 ASSERT_EQ(std::string(kReadData, strlen(kReadData)),
271 std::string((const char*)output, strlen(kReadData)));
272 input_stream()->Reset();
273 ASSERT_EQ(strlen(kReadData2),
274 DoInputStreamRead(strlen(kReadData2), true, &output));
275 ASSERT_EQ(std::string(kReadData2, strlen(kReadData2)),
276 std::string((const char*)output, strlen(kReadData2)));
277 }
278
279 // Simulate a read timing out.
280 TEST_F(GCMSocketStreamTest, ReadTimeout) {
281 int result = net::ERR_TIMED_OUT;
282 std::string original_data = std::string(kReadData);
283 std::string partial_data = original_data.substr(original_data.size()/2);
284 const void* output = NULL;
285
286 // Send part of the data.
287 data_provider()->AddRead(net::MockRead(net::ASYNC,
288 partial_data.c_str(),
289 partial_data.length()));
290 ASSERT_EQ(partial_data.length(),
291 DoInputStreamRead(original_data.length(), true, &output));
292 ASSERT_EQ(SocketInputStream::CLOSED, input_stream()->state());
293 ASSERT_EQ(result, input_stream()->last_error());
294
295 // Send the rest of the data. Should have no effect.
296 data_provider()->AddRead(
297 net::MockRead(net::ASYNC,
298 &original_data.c_str()[partial_data.size()],
299 original_data.size() - partial_data.size()));
300 ASSERT_EQ(SocketInputStream::CLOSED, input_stream()->state());
301 ASSERT_EQ(result, input_stream()->last_error());
302 }
303
304 // Simulate a read that is aborted.
305 TEST_F(GCMSocketStreamTest, ReadError) {
306 int result = net::ERR_ABORTED;
307 const void* output = NULL;
308 data_provider()->AddRead(net::MockRead(net::SYNCHRONOUS, result));
309 ASSERT_EQ(0U, DoInputStreamRead(strlen(kReadData), true, &output));
310 ASSERT_EQ(SocketInputStream::CLOSED, input_stream()->state());
311 ASSERT_EQ(result, input_stream()->last_error());
312 }
313
314 // Simulate a read after the connection is closed.
315 TEST_F(GCMSocketStreamTest, ReadDisconnected) {
316 socket()->Disconnect();
317 const void* output = NULL;
318 ASSERT_EQ(0U, DoInputStreamRead(strlen(kReadData), true, &output));
319 ASSERT_EQ(SocketInputStream::CLOSED, input_stream()->state());
320 ASSERT_EQ(net::ERR_CONNECTION_CLOSED, input_stream()->last_error());
321 }
322
323 // Write a full message in one go.
324 TEST_F(GCMSocketStreamTest, WriteFull) {
325 data_provider()->AddWrite(net::MockWrite(kWriteData));
326 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
327 }
328
329 // Write a message in two go's.
330 TEST_F(GCMSocketStreamTest, WritePartial) {
331 std::string full_data = std::string(kWriteData);
332 std::string part1 = full_data.substr(0, full_data.length()/2);
333 std::string part2 = full_data.substr(full_data.length()/2);
334 data_provider()->AddWrite(net::MockWrite(part1.c_str()));
335 data_provider()->AddWrite(net::MockWrite(part2.c_str()));
336 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
337 }
338
339 // Write a message completely asynchronously (returns IO_PENDING before
340 // finishing the write in two go's).
341 TEST_F(GCMSocketStreamTest, WriteNone) {
342 std::string full_data = std::string(kWriteData);
343 std::string part1 = full_data.substr(0, full_data.length()/2);
344 std::string part2 = full_data.substr(full_data.length()/2);
345 message_loop()->PostTask(
346 FROM_HERE,
347 base::Bind(&SocketStreamTestDataProvider::AddWrite,
348 base::Unretained(data_provider()),
349 net::MockWrite(part1.c_str())));
350 message_loop()->PostTask(
351 FROM_HERE,
352 base::Bind(&SocketStreamTestDataProvider::AddWrite,
353 base::Unretained(data_provider()),
354 net::MockWrite(part2.c_str())));
355 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
356 }
357
358 // Write a message then read a message.
359 TEST_F(GCMSocketStreamTest, WriteThenRead) {
360 data_provider()->AddWrite(net::MockWrite(kWriteData));
361 data_provider()->AddRead(net::MockRead(kReadData));
362 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
363 const void* output = NULL;
364 ASSERT_EQ(strlen(kReadData),
365 DoInputStreamRead(strlen(kReadData), false, &output));
366 ASSERT_EQ(std::string(kReadData),
367 std::string((const char*)output, strlen(kReadData)));
368 }
369
370 // Read a message then write a message.
371 TEST_F(GCMSocketStreamTest, ReadThenWrite) {
372 data_provider()->AddRead(net::MockRead(kReadData));
373 data_provider()->AddWrite(net::MockWrite(kWriteData));
374 const void* output = NULL;
375 ASSERT_EQ(strlen(kReadData),
376 DoInputStreamRead(strlen(kReadData), false, &output));
377 ASSERT_EQ(std::string(kReadData),
378 std::string((const char*)output, strlen(kReadData)));
379 ASSERT_EQ(strlen(kWriteData), DoOutputStreamWrite(strlen(kWriteData)));
380 }
381
382 // Simulate a write that gets aborted.
383 TEST_F(GCMSocketStreamTest, WriteError) {
384 int result = net::ERR_ABORTED;
385 data_provider()->AddWrite(net::MockWrite(net::SYNCHRONOUS,
386 result));
387 DoOutputStreamWrite(strlen(kWriteData));
388 ASSERT_EQ(SocketOutputStream::CLOSED, output_stream()->state());
389 ASSERT_EQ(result, output_stream()->last_error());
390 }
391
392 // Simulate a write after the connection is closed.
393 TEST_F(GCMSocketStreamTest, WriteDisconnected) {
394 socket()->Disconnect();
395 DoOutputStreamWrite(strlen(kWriteData));
396 ASSERT_EQ(SocketOutputStream::CLOSED, output_stream()->state());
397 ASSERT_EQ(net::ERR_CONNECTION_CLOSED, output_stream()->last_error());
398 }
399
400 } // namespace
401 } // namespace gcm
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698