Roll src/third_party/WebKit 3529d49:06e8485 (svn 202554:202555)
[chromium-blink-merge.git] / google_apis / gcm / base / socket_stream_unittest.cc
blob3ca5d00748f08dabb3d6cc73bbcd07a869250d19
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.
5 #include "google_apis/gcm/base/socket_stream.h"
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/stl_util.h"
12 #include "base/strings/string_piece.h"
13 #include "net/socket/socket_test_util.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 namespace gcm {
17 namespace {
19 typedef std::vector<net::MockRead> ReadList;
20 typedef std::vector<net::MockWrite> WriteList;
22 const char kReadData[] = "read_data";
23 const int kReadDataSize = arraysize(kReadData) - 1;
24 const char kReadData2[] = "read_alternate_data";
25 const int kReadData2Size = arraysize(kReadData2) - 1;
26 const char kWriteData[] = "write_data";
27 const int kWriteDataSize = arraysize(kWriteData) - 1;
29 class GCMSocketStreamTest : public testing::Test {
30 public:
31 GCMSocketStreamTest();
32 ~GCMSocketStreamTest() override;
34 // Build a socket with the expected reads and writes.
35 void BuildSocket(const ReadList& read_list, const WriteList& write_list);
37 // Pump the message loop until idle.
38 void PumpLoop();
40 // Simulates a google::protobuf::io::CodedInputStream read.
41 base::StringPiece DoInputStreamRead(int bytes);
42 // Simulates a google::protobuf::io::CodedOutputStream write.
43 int DoOutputStreamWrite(const base::StringPiece& write_src);
45 // Synchronous Refresh wrapper.
46 void WaitForData(int msg_size);
48 base::MessageLoop* message_loop() { return &message_loop_; };
49 net::StaticSocketDataProvider* data_provider() {
50 return data_provider_.get();
52 SocketInputStream* input_stream() { return socket_input_stream_.get(); }
53 SocketOutputStream* output_stream() { return socket_output_stream_.get(); }
54 net::StreamSocket* socket() { return socket_.get(); }
56 private:
57 void OpenConnection();
58 void ResetInputStream();
59 void ResetOutputStream();
61 void ConnectCallback(int result);
63 // SocketStreams and their data providers.
64 ReadList mock_reads_;
65 WriteList mock_writes_;
66 scoped_ptr<net::StaticSocketDataProvider> data_provider_;
67 scoped_ptr<SocketInputStream> socket_input_stream_;
68 scoped_ptr<SocketOutputStream> socket_output_stream_;
70 // net:: components.
71 scoped_ptr<net::StreamSocket> socket_;
72 net::MockClientSocketFactory socket_factory_;
73 net::AddressList address_list_;
75 base::MessageLoopForIO message_loop_;
78 GCMSocketStreamTest::GCMSocketStreamTest() {
79 net::IPAddressNumber ip_number;
80 net::ParseIPLiteralToNumber("127.0.0.1", &ip_number);
81 address_list_ = net::AddressList::CreateFromIPAddress(ip_number, 5228);
84 GCMSocketStreamTest::~GCMSocketStreamTest() {}
86 void GCMSocketStreamTest::BuildSocket(const ReadList& read_list,
87 const WriteList& write_list) {
88 mock_reads_ = read_list;
89 mock_writes_ = write_list;
90 data_provider_.reset(
91 new net::StaticSocketDataProvider(
92 vector_as_array(&mock_reads_), mock_reads_.size(),
93 vector_as_array(&mock_writes_), mock_writes_.size()));
94 socket_factory_.AddSocketDataProvider(data_provider_.get());
95 OpenConnection();
96 ResetInputStream();
97 ResetOutputStream();
100 void GCMSocketStreamTest::PumpLoop() {
101 base::RunLoop run_loop;
102 run_loop.RunUntilIdle();
105 base::StringPiece GCMSocketStreamTest::DoInputStreamRead(int bytes) {
106 int total_bytes_read = 0;
107 const void* initial_buffer = NULL;
108 const void* buffer = NULL;
109 int size = 0;
111 do {
112 DCHECK(socket_input_stream_->GetState() == SocketInputStream::EMPTY ||
113 socket_input_stream_->GetState() == SocketInputStream::READY);
114 if (!socket_input_stream_->Next(&buffer, &size))
115 break;
116 total_bytes_read += size;
117 if (initial_buffer) { // Verify the buffer doesn't skip data.
118 EXPECT_EQ(static_cast<const uint8*>(initial_buffer) + total_bytes_read,
119 static_cast<const uint8*>(buffer) + size);
120 } else {
121 initial_buffer = buffer;
123 } while (total_bytes_read < bytes);
125 if (total_bytes_read > bytes) {
126 socket_input_stream_->BackUp(total_bytes_read - bytes);
127 total_bytes_read = bytes;
130 return base::StringPiece(static_cast<const char*>(initial_buffer),
131 total_bytes_read);
134 int GCMSocketStreamTest::DoOutputStreamWrite(
135 const base::StringPiece& write_src) {
136 DCHECK_EQ(socket_output_stream_->GetState(), SocketOutputStream::EMPTY);
137 int total_bytes_written = 0;
138 void* buffer = NULL;
139 int size = 0;
140 int bytes = write_src.size();
142 do {
143 if (!socket_output_stream_->Next(&buffer, &size))
144 break;
145 int bytes_to_write = (size < bytes ? size : bytes);
146 memcpy(buffer,
147 write_src.data() + total_bytes_written,
148 bytes_to_write);
149 if (bytes_to_write < size)
150 socket_output_stream_->BackUp(size - bytes_to_write);
151 total_bytes_written += bytes_to_write;
152 } while (total_bytes_written < bytes);
154 base::RunLoop run_loop;
155 if (socket_output_stream_->Flush(run_loop.QuitClosure()) ==
156 net::ERR_IO_PENDING) {
157 run_loop.Run();
160 return total_bytes_written;
163 void GCMSocketStreamTest::WaitForData(int msg_size) {
164 while (input_stream()->UnreadByteCount() < msg_size) {
165 base::RunLoop run_loop;
166 if (input_stream()->Refresh(run_loop.QuitClosure(),
167 msg_size - input_stream()->UnreadByteCount()) ==
168 net::ERR_IO_PENDING) {
169 run_loop.Run();
171 if (input_stream()->GetState() == SocketInputStream::CLOSED)
172 return;
176 void GCMSocketStreamTest::OpenConnection() {
177 socket_ = socket_factory_.CreateTransportClientSocket(
178 address_list_, NULL, net::NetLog::Source());
179 socket_->Connect(
180 base::Bind(&GCMSocketStreamTest::ConnectCallback,
181 base::Unretained(this)));
182 PumpLoop();
185 void GCMSocketStreamTest::ConnectCallback(int result) {}
187 void GCMSocketStreamTest::ResetInputStream() {
188 DCHECK(socket_.get());
189 socket_input_stream_.reset(new SocketInputStream(socket_.get()));
192 void GCMSocketStreamTest::ResetOutputStream() {
193 DCHECK(socket_.get());
194 socket_output_stream_.reset(new SocketOutputStream(socket_.get()));
197 // A read where all data is already available.
198 TEST_F(GCMSocketStreamTest, ReadDataSync) {
199 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS,
200 kReadData,
201 kReadDataSize)),
202 WriteList());
204 WaitForData(kReadDataSize);
205 ASSERT_EQ(std::string(kReadData, kReadDataSize),
206 DoInputStreamRead(kReadDataSize));
209 // A read that comes in two parts.
210 TEST_F(GCMSocketStreamTest, ReadPartialDataSync) {
211 int first_read_len = kReadDataSize / 2;
212 int second_read_len = kReadDataSize - first_read_len;
213 ReadList read_list;
214 read_list.push_back(
215 net::MockRead(net::SYNCHRONOUS,
216 kReadData,
217 first_read_len));
218 read_list.push_back(
219 net::MockRead(net::SYNCHRONOUS,
220 &kReadData[first_read_len],
221 second_read_len));
222 BuildSocket(read_list, WriteList());
224 WaitForData(kReadDataSize);
225 ASSERT_EQ(std::string(kReadData, kReadDataSize),
226 DoInputStreamRead(kReadDataSize));
229 // A read where no data is available at first (IO_PENDING will be returned).
230 TEST_F(GCMSocketStreamTest, ReadAsync) {
231 int first_read_len = kReadDataSize / 2;
232 int second_read_len = kReadDataSize - first_read_len;
233 ReadList read_list;
234 read_list.push_back(
235 net::MockRead(net::ASYNC, kReadData, first_read_len));
236 read_list.push_back(
237 net::MockRead(net::ASYNC, &kReadData[first_read_len], second_read_len));
238 BuildSocket(read_list, WriteList());
239 WaitForData(kReadDataSize);
240 ASSERT_EQ(std::string(kReadData, kReadDataSize),
241 DoInputStreamRead(kReadDataSize));
244 // Simulate two packets arriving at once. Read them in two separate calls.
245 TEST_F(GCMSocketStreamTest, TwoReadsAtOnce) {
246 std::string long_data = std::string(kReadData, kReadDataSize) +
247 std::string(kReadData2, kReadData2Size);
248 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS,
249 long_data.c_str(),
250 long_data.size())),
251 WriteList());
253 WaitForData(kReadDataSize);
254 ASSERT_EQ(std::string(kReadData, kReadDataSize),
255 DoInputStreamRead(kReadDataSize));
257 WaitForData(kReadData2Size);
258 ASSERT_EQ(std::string(kReadData2, kReadData2Size),
259 DoInputStreamRead(kReadData2Size));
262 // Simulate two packets arriving at once. Read them in two calls separated
263 // by a Rebuild.
264 TEST_F(GCMSocketStreamTest, TwoReadsAtOnceWithRebuild) {
265 std::string long_data = std::string(kReadData, kReadDataSize) +
266 std::string(kReadData2, kReadData2Size);
267 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS,
268 long_data.c_str(),
269 long_data.size())),
270 WriteList());
272 WaitForData(kReadDataSize);
273 ASSERT_EQ(std::string(kReadData, kReadDataSize),
274 DoInputStreamRead(kReadDataSize));
276 input_stream()->RebuildBuffer();
277 WaitForData(kReadData2Size);
278 ASSERT_EQ(std::string(kReadData2, kReadData2Size),
279 DoInputStreamRead(kReadData2Size));
282 // Simulate a read that is aborted.
283 TEST_F(GCMSocketStreamTest, ReadError) {
284 int result = net::ERR_ABORTED;
285 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS, result)),
286 WriteList());
288 WaitForData(kReadDataSize);
289 ASSERT_EQ(SocketInputStream::CLOSED, input_stream()->GetState());
290 ASSERT_EQ(result, input_stream()->last_error());
293 // Simulate a read after the connection is closed.
294 TEST_F(GCMSocketStreamTest, ReadDisconnected) {
295 BuildSocket(ReadList(), WriteList());
296 socket()->Disconnect();
297 WaitForData(kReadDataSize);
298 ASSERT_EQ(SocketInputStream::CLOSED, input_stream()->GetState());
299 ASSERT_EQ(net::ERR_CONNECTION_CLOSED, input_stream()->last_error());
302 // Write a full message in one go.
303 TEST_F(GCMSocketStreamTest, WriteFull) {
304 BuildSocket(ReadList(),
305 WriteList(1, net::MockWrite(net::SYNCHRONOUS,
306 kWriteData,
307 kWriteDataSize)));
308 ASSERT_EQ(kWriteDataSize,
309 DoOutputStreamWrite(base::StringPiece(kWriteData,
310 kWriteDataSize)));
313 // Write a message in two go's.
314 TEST_F(GCMSocketStreamTest, WritePartial) {
315 WriteList write_list;
316 write_list.push_back(net::MockWrite(net::SYNCHRONOUS,
317 kWriteData,
318 kWriteDataSize / 2));
319 write_list.push_back(net::MockWrite(net::SYNCHRONOUS,
320 kWriteData + kWriteDataSize / 2,
321 kWriteDataSize / 2));
322 BuildSocket(ReadList(), write_list);
323 ASSERT_EQ(kWriteDataSize,
324 DoOutputStreamWrite(base::StringPiece(kWriteData,
325 kWriteDataSize)));
328 // Write a message completely asynchronously (returns IO_PENDING before
329 // finishing the write in two go's).
330 TEST_F(GCMSocketStreamTest, WriteNone) {
331 WriteList write_list;
332 write_list.push_back(net::MockWrite(net::SYNCHRONOUS,
333 kWriteData,
334 kWriteDataSize / 2));
335 write_list.push_back(net::MockWrite(net::SYNCHRONOUS,
336 kWriteData + kWriteDataSize / 2,
337 kWriteDataSize / 2));
338 BuildSocket(ReadList(), write_list);
339 ASSERT_EQ(kWriteDataSize,
340 DoOutputStreamWrite(base::StringPiece(kWriteData,
341 kWriteDataSize)));
344 // Write a message then read a message.
345 TEST_F(GCMSocketStreamTest, WriteThenRead) {
346 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS,
347 kReadData,
348 kReadDataSize)),
349 WriteList(1, net::MockWrite(net::SYNCHRONOUS,
350 kWriteData,
351 kWriteDataSize)));
353 ASSERT_EQ(kWriteDataSize,
354 DoOutputStreamWrite(base::StringPiece(kWriteData,
355 kWriteDataSize)));
357 WaitForData(kReadDataSize);
358 ASSERT_EQ(std::string(kReadData, kReadDataSize),
359 DoInputStreamRead(kReadDataSize));
362 // Read a message then write a message.
363 TEST_F(GCMSocketStreamTest, ReadThenWrite) {
364 BuildSocket(ReadList(1, net::MockRead(net::SYNCHRONOUS,
365 kReadData,
366 kReadDataSize)),
367 WriteList(1, net::MockWrite(net::SYNCHRONOUS,
368 kWriteData,
369 kWriteDataSize)));
371 WaitForData(kReadDataSize);
372 ASSERT_EQ(std::string(kReadData, kReadDataSize),
373 DoInputStreamRead(kReadDataSize));
375 ASSERT_EQ(kWriteDataSize,
376 DoOutputStreamWrite(base::StringPiece(kWriteData,
377 kWriteDataSize)));
380 // Simulate a write that gets aborted.
381 TEST_F(GCMSocketStreamTest, WriteError) {
382 int result = net::ERR_ABORTED;
383 BuildSocket(ReadList(),
384 WriteList(1, net::MockWrite(net::SYNCHRONOUS, result)));
385 DoOutputStreamWrite(base::StringPiece(kWriteData, kWriteDataSize));
386 ASSERT_EQ(SocketOutputStream::CLOSED, output_stream()->GetState());
387 ASSERT_EQ(result, output_stream()->last_error());
390 // Simulate a write after the connection is closed.
391 TEST_F(GCMSocketStreamTest, WriteDisconnected) {
392 BuildSocket(ReadList(), WriteList());
393 socket()->Disconnect();
394 DoOutputStreamWrite(base::StringPiece(kWriteData, kWriteDataSize));
395 ASSERT_EQ(SocketOutputStream::CLOSED, output_stream()->GetState());
396 ASSERT_EQ(net::ERR_CONNECTION_CLOSED, output_stream()->last_error());
399 } // namespace
400 } // namespace gcm