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/engine/connection_handler_impl.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/run_loop.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/test/test_timeouts.h"
12 #include "google/protobuf/io/coded_stream.h"
13 #include "google/protobuf/io/zero_copy_stream_impl_lite.h"
14 #include "google_apis/gcm/base/mcs_util.h"
15 #include "google_apis/gcm/base/socket_stream.h"
16 #include "google_apis/gcm/protocol/mcs.pb.h"
17 #include "net/socket/socket_test_util.h"
18 #include "net/socket/stream_socket.h"
19 #include "testing/gtest/include/gtest/gtest.h"
24 typedef scoped_ptr
<google::protobuf::MessageLite
> ScopedMessage
;
25 typedef std::vector
<net::MockRead
> ReadList
;
26 typedef std::vector
<net::MockWrite
> WriteList
;
28 const uint64 kAuthId
= 54321;
29 const uint64 kAuthToken
= 12345;
30 const char kMCSVersion
= 41; // The protocol version.
31 const int kMCSPort
= 5228; // The server port.
32 const char kDataMsgFrom
[] = "data_from";
33 const char kDataMsgCategory
[] = "data_category";
34 const char kDataMsgFrom2
[] = "data_from2";
35 const char kDataMsgCategory2
[] = "data_category2";
36 const char kDataMsgFromLong
[] =
37 "this is a long from that will result in a message > 128 bytes";
38 const char kDataMsgCategoryLong
[] =
39 "this is a long category that will result in a message > 128 bytes";
40 const char kDataMsgFromLong2
[] =
41 "this is a second long from that will result in a message > 128 bytes";
42 const char kDataMsgCategoryLong2
[] =
43 "this is a second long category that will result in a message > 128 bytes";
45 // ---- Helpers for building messages. ----
47 // Encode a protobuf packet with protobuf type |tag| and serialized protobuf
48 // bytes |proto| into the MCS message form (tag + varint size + bytes).
49 std::string
EncodePacket(uint8 tag
, const std::string
& proto
) {
51 google::protobuf::io::StringOutputStream
string_output_stream(&result
);
53 google::protobuf::io::CodedOutputStream
coded_output_stream(
54 &string_output_stream
);
55 const unsigned char tag_byte
[1] = { tag
};
56 coded_output_stream
.WriteRaw(tag_byte
, 1);
57 coded_output_stream
.WriteVarint32(proto
.size());
58 coded_output_stream
.WriteRaw(proto
.c_str(), proto
.size());
59 // ~CodedOutputStream must run before the move constructor at the
60 // return statement. http://crbug.com/338962
65 // Encode a handshake request into the MCS message form.
66 std::string
EncodeHandshakeRequest() {
68 const char version_byte
[1] = {kMCSVersion
};
69 result
.append(version_byte
, 1);
70 ScopedMessage
login_request(
71 BuildLoginRequest(kAuthId
, kAuthToken
, ""));
72 result
.append(EncodePacket(kLoginRequestTag
,
73 login_request
->SerializeAsString()));
77 // Build a serialized login response protobuf.
78 std::string
BuildLoginResponse() {
80 mcs_proto::LoginResponse login_response
;
81 login_response
.set_id("id");
82 result
.append(login_response
.SerializeAsString());
86 // Encoode a handshake response into the MCS message form.
87 std::string
EncodeHandshakeResponse() {
89 const char version_byte
[1] = {kMCSVersion
};
90 result
.append(version_byte
, 1);
91 result
.append(EncodePacket(kLoginResponseTag
, BuildLoginResponse()));
95 // Build a serialized data message stanza protobuf.
96 std::string
BuildDataMessage(const std::string
& from
,
97 const std::string
& category
) {
99 mcs_proto::DataMessageStanza data_message
;
100 data_message
.set_from(from
);
101 data_message
.set_category(category
);
102 return data_message
.SerializeAsString();
105 class GCMConnectionHandlerImplTest
: public testing::Test
{
107 GCMConnectionHandlerImplTest();
108 virtual ~GCMConnectionHandlerImplTest();
110 net::StreamSocket
* BuildSocket(const ReadList
& read_list
,
111 const WriteList
& write_list
);
113 // Pump |message_loop_|, resetting |run_loop_| after completion.
116 ConnectionHandlerImpl
* connection_handler() {
117 return connection_handler_
.get();
119 base::MessageLoop
* message_loop() { return &message_loop_
; };
120 net::DelayedSocketData
* data_provider() { return data_provider_
.get(); }
121 int last_error() const { return last_error_
; }
123 // Initialize the connection handler, setting |dst_proto| as the destination
124 // for any received messages.
125 void Connect(ScopedMessage
* dst_proto
);
127 // Runs the message loop until a message is received.
128 void WaitForMessage();
131 void ReadContinuation(ScopedMessage
* dst_proto
, ScopedMessage new_proto
);
132 void WriteContinuation();
133 void ConnectionContinuation(int error
);
135 // SocketStreams and their data provider.
136 ReadList mock_reads_
;
137 WriteList mock_writes_
;
138 scoped_ptr
<net::DelayedSocketData
> data_provider_
;
139 scoped_ptr
<SocketInputStream
> socket_input_stream_
;
140 scoped_ptr
<SocketOutputStream
> socket_output_stream_
;
142 // The connection handler being tested.
143 scoped_ptr
<ConnectionHandlerImpl
> connection_handler_
;
145 // The last connection error received.
149 scoped_ptr
<net::StreamSocket
> socket_
;
150 net::MockClientSocketFactory socket_factory_
;
151 net::AddressList address_list_
;
153 base::MessageLoopForIO message_loop_
;
154 scoped_ptr
<base::RunLoop
> run_loop_
;
157 GCMConnectionHandlerImplTest::GCMConnectionHandlerImplTest()
159 net::IPAddressNumber ip_number
;
160 net::ParseIPLiteralToNumber("127.0.0.1", &ip_number
);
161 address_list_
= net::AddressList::CreateFromIPAddress(ip_number
, kMCSPort
);
164 GCMConnectionHandlerImplTest::~GCMConnectionHandlerImplTest() {
167 net::StreamSocket
* GCMConnectionHandlerImplTest::BuildSocket(
168 const ReadList
& read_list
,
169 const WriteList
& write_list
) {
170 mock_reads_
= read_list
;
171 mock_writes_
= write_list
;
172 data_provider_
.reset(
173 new net::DelayedSocketData(0,
174 &(mock_reads_
[0]), mock_reads_
.size(),
175 &(mock_writes_
[0]), mock_writes_
.size()));
176 socket_factory_
.AddSocketDataProvider(data_provider_
.get());
178 socket_
= socket_factory_
.CreateTransportClientSocket(
179 address_list_
, NULL
, net::NetLog::Source());
180 socket_
->Connect(net::CompletionCallback());
182 run_loop_
.reset(new base::RunLoop());
185 DCHECK(socket_
->IsConnected());
186 return socket_
.get();
189 void GCMConnectionHandlerImplTest::PumpLoop() {
190 run_loop_
->RunUntilIdle();
191 run_loop_
.reset(new base::RunLoop());
194 void GCMConnectionHandlerImplTest::Connect(
195 ScopedMessage
* dst_proto
) {
196 connection_handler_
.reset(new ConnectionHandlerImpl(
197 TestTimeouts::tiny_timeout(),
198 base::Bind(&GCMConnectionHandlerImplTest::ReadContinuation
,
199 base::Unretained(this),
201 base::Bind(&GCMConnectionHandlerImplTest::WriteContinuation
,
202 base::Unretained(this)),
203 base::Bind(&GCMConnectionHandlerImplTest::ConnectionContinuation
,
204 base::Unretained(this))));
205 EXPECT_FALSE(connection_handler()->CanSendMessage());
206 connection_handler_
->Init(
207 *BuildLoginRequest(kAuthId
, kAuthToken
, ""),
211 void GCMConnectionHandlerImplTest::ReadContinuation(
212 ScopedMessage
* dst_proto
,
213 ScopedMessage new_proto
) {
214 *dst_proto
= new_proto
.Pass();
218 void GCMConnectionHandlerImplTest::WaitForMessage() {
220 run_loop_
.reset(new base::RunLoop());
223 void GCMConnectionHandlerImplTest::WriteContinuation() {
227 void GCMConnectionHandlerImplTest::ConnectionContinuation(int error
) {
232 // Initialize the connection handler and ensure the handshake completes
234 TEST_F(GCMConnectionHandlerImplTest
, Init
) {
235 std::string handshake_request
= EncodeHandshakeRequest();
236 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
237 handshake_request
.c_str(),
238 handshake_request
.size()));
239 std::string handshake_response
= EncodeHandshakeResponse();
240 ReadList
read_list(1, net::MockRead(net::ASYNC
,
241 handshake_response
.c_str(),
242 handshake_response
.size()));
243 BuildSocket(read_list
, write_list
);
245 ScopedMessage received_message
;
246 Connect(&received_message
);
247 EXPECT_FALSE(connection_handler()->CanSendMessage());
248 WaitForMessage(); // The login send.
249 WaitForMessage(); // The login response.
250 ASSERT_TRUE(received_message
.get());
251 EXPECT_EQ(BuildLoginResponse(), received_message
->SerializeAsString());
252 EXPECT_TRUE(connection_handler()->CanSendMessage());
255 // Simulate the handshake response returning an older version. Initialization
257 TEST_F(GCMConnectionHandlerImplTest
, InitFailedVersionCheck
) {
258 std::string handshake_request
= EncodeHandshakeRequest();
259 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
260 handshake_request
.c_str(),
261 handshake_request
.size()));
262 std::string handshake_response
= EncodeHandshakeResponse();
263 // Overwrite the version byte.
264 handshake_response
[0] = 37;
265 ReadList
read_list(1, net::MockRead(net::ASYNC
,
266 handshake_response
.c_str(),
267 handshake_response
.size()));
268 BuildSocket(read_list
, write_list
);
270 ScopedMessage received_message
;
271 Connect(&received_message
);
272 WaitForMessage(); // The login send.
273 WaitForMessage(); // The login response. Should result in a connection error.
274 EXPECT_FALSE(received_message
.get());
275 EXPECT_FALSE(connection_handler()->CanSendMessage());
276 EXPECT_EQ(net::ERR_FAILED
, last_error());
279 // Attempt to initialize, but receive no server response, resulting in a time
281 TEST_F(GCMConnectionHandlerImplTest
, InitTimeout
) {
282 std::string handshake_request
= EncodeHandshakeRequest();
283 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
284 handshake_request
.c_str(),
285 handshake_request
.size()));
286 ReadList
read_list(1, net::MockRead(net::SYNCHRONOUS
,
287 net::ERR_IO_PENDING
));
288 BuildSocket(read_list
, write_list
);
290 ScopedMessage received_message
;
291 Connect(&received_message
);
292 WaitForMessage(); // The login send.
293 WaitForMessage(); // The login response. Should result in a connection error.
294 EXPECT_FALSE(received_message
.get());
295 EXPECT_FALSE(connection_handler()->CanSendMessage());
296 EXPECT_EQ(net::ERR_TIMED_OUT
, last_error());
299 // Attempt to initialize, but receive an incomplete server response, resulting
301 TEST_F(GCMConnectionHandlerImplTest
, InitIncompleteTimeout
) {
302 std::string handshake_request
= EncodeHandshakeRequest();
303 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
304 handshake_request
.c_str(),
305 handshake_request
.size()));
306 std::string handshake_response
= EncodeHandshakeResponse();
308 read_list
.push_back(net::MockRead(net::ASYNC
,
309 handshake_response
.c_str(),
310 handshake_response
.size() / 2));
311 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
312 net::ERR_IO_PENDING
));
313 BuildSocket(read_list
, write_list
);
315 ScopedMessage received_message
;
316 Connect(&received_message
);
317 WaitForMessage(); // The login send.
318 WaitForMessage(); // The login response. Should result in a connection error.
319 EXPECT_FALSE(received_message
.get());
320 EXPECT_FALSE(connection_handler()->CanSendMessage());
321 EXPECT_EQ(net::ERR_TIMED_OUT
, last_error());
324 // Reinitialize the connection handler after failing to initialize.
325 TEST_F(GCMConnectionHandlerImplTest
, ReInit
) {
326 std::string handshake_request
= EncodeHandshakeRequest();
327 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
328 handshake_request
.c_str(),
329 handshake_request
.size()));
330 ReadList
read_list(1, net::MockRead(net::SYNCHRONOUS
,
331 net::ERR_IO_PENDING
));
332 BuildSocket(read_list
, write_list
);
334 ScopedMessage received_message
;
335 Connect(&received_message
);
336 WaitForMessage(); // The login send.
337 WaitForMessage(); // The login response. Should result in a connection error.
338 EXPECT_FALSE(received_message
.get());
339 EXPECT_FALSE(connection_handler()->CanSendMessage());
340 EXPECT_EQ(net::ERR_TIMED_OUT
, last_error());
342 // Build a new socket and reconnect, successfully this time.
343 std::string handshake_response
= EncodeHandshakeResponse();
344 read_list
[0] = net::MockRead(net::ASYNC
,
345 handshake_response
.c_str(),
346 handshake_response
.size());
347 BuildSocket(read_list
, write_list
);
348 Connect(&received_message
);
349 EXPECT_FALSE(connection_handler()->CanSendMessage());
350 WaitForMessage(); // The login send.
351 WaitForMessage(); // The login response.
352 ASSERT_TRUE(received_message
.get());
353 EXPECT_EQ(BuildLoginResponse(), received_message
->SerializeAsString());
354 EXPECT_TRUE(connection_handler()->CanSendMessage());
357 // Verify that messages can be received after initialization.
358 TEST_F(GCMConnectionHandlerImplTest
, RecvMsg
) {
359 std::string handshake_request
= EncodeHandshakeRequest();
360 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
361 handshake_request
.c_str(),
362 handshake_request
.size()));
363 std::string handshake_response
= EncodeHandshakeResponse();
365 std::string data_message_proto
= BuildDataMessage(kDataMsgFrom
,
367 std::string data_message_pkt
=
368 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
370 read_list
.push_back(net::MockRead(net::ASYNC
,
371 handshake_response
.c_str(),
372 handshake_response
.size()));
373 read_list
.push_back(net::MockRead(net::ASYNC
,
374 data_message_pkt
.c_str(),
375 data_message_pkt
.size()));
376 BuildSocket(read_list
, write_list
);
378 ScopedMessage received_message
;
379 Connect(&received_message
);
380 WaitForMessage(); // The login send.
381 WaitForMessage(); // The login response.
382 WaitForMessage(); // The data message.
383 ASSERT_TRUE(received_message
.get());
384 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
385 EXPECT_EQ(net::OK
, last_error());
388 // Verify that if two messages arrive at once, they're treated appropriately.
389 TEST_F(GCMConnectionHandlerImplTest
, Recv2Msgs
) {
390 std::string handshake_request
= EncodeHandshakeRequest();
391 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
392 handshake_request
.c_str(),
393 handshake_request
.size()));
394 std::string handshake_response
= EncodeHandshakeResponse();
396 std::string data_message_proto
= BuildDataMessage(kDataMsgFrom
,
398 std::string data_message_proto2
= BuildDataMessage(kDataMsgFrom2
,
400 std::string data_message_pkt
=
401 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
402 data_message_pkt
+= EncodePacket(kDataMessageStanzaTag
, data_message_proto2
);
404 read_list
.push_back(net::MockRead(net::ASYNC
,
405 handshake_response
.c_str(),
406 handshake_response
.size()));
407 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
408 data_message_pkt
.c_str(),
409 data_message_pkt
.size()));
410 BuildSocket(read_list
, write_list
);
412 ScopedMessage received_message
;
413 Connect(&received_message
);
414 WaitForMessage(); // The login send.
415 WaitForMessage(); // The login response.
416 WaitForMessage(); // The first data message.
417 ASSERT_TRUE(received_message
.get());
418 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
419 received_message
.reset();
420 WaitForMessage(); // The second data message.
421 ASSERT_TRUE(received_message
.get());
422 EXPECT_EQ(data_message_proto2
, received_message
->SerializeAsString());
423 EXPECT_EQ(net::OK
, last_error());
426 // Receive a long (>128 bytes) message.
427 TEST_F(GCMConnectionHandlerImplTest
, RecvLongMsg
) {
428 std::string handshake_request
= EncodeHandshakeRequest();
429 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
430 handshake_request
.c_str(),
431 handshake_request
.size()));
432 std::string handshake_response
= EncodeHandshakeResponse();
434 std::string data_message_proto
=
435 BuildDataMessage(kDataMsgFromLong
, kDataMsgCategoryLong
);
436 std::string data_message_pkt
=
437 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
438 DCHECK_GT(data_message_pkt
.size(), 128U);
440 read_list
.push_back(net::MockRead(net::ASYNC
,
441 handshake_response
.c_str(),
442 handshake_response
.size()));
443 read_list
.push_back(net::MockRead(net::ASYNC
,
444 data_message_pkt
.c_str(),
445 data_message_pkt
.size()));
446 BuildSocket(read_list
, write_list
);
448 ScopedMessage received_message
;
449 Connect(&received_message
);
450 WaitForMessage(); // The login send.
451 WaitForMessage(); // The login response.
452 WaitForMessage(); // The data message.
453 ASSERT_TRUE(received_message
.get());
454 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
455 EXPECT_EQ(net::OK
, last_error());
458 // Receive a long (>128 bytes) message in two synchronous parts.
459 TEST_F(GCMConnectionHandlerImplTest
, RecvLongMsg2Parts
) {
460 std::string handshake_request
= EncodeHandshakeRequest();
461 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
462 handshake_request
.c_str(),
463 handshake_request
.size()));
464 std::string handshake_response
= EncodeHandshakeResponse();
466 std::string data_message_proto
=
467 BuildDataMessage(kDataMsgFromLong
, kDataMsgCategoryLong
);
468 std::string data_message_pkt
=
469 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
470 DCHECK_GT(data_message_pkt
.size(), 128U);
472 read_list
.push_back(net::MockRead(net::ASYNC
,
473 handshake_response
.c_str(),
474 handshake_response
.size()));
476 int bytes_in_first_message
= data_message_pkt
.size() / 2;
477 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
478 data_message_pkt
.c_str(),
479 bytes_in_first_message
));
480 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
481 data_message_pkt
.c_str() +
482 bytes_in_first_message
,
483 data_message_pkt
.size() -
484 bytes_in_first_message
));
485 BuildSocket(read_list
, write_list
);
487 ScopedMessage received_message
;
488 Connect(&received_message
);
489 WaitForMessage(); // The login send.
490 WaitForMessage(); // The login response.
491 WaitForMessage(); // The data message.
492 ASSERT_TRUE(received_message
.get());
493 EXPECT_EQ(net::OK
, last_error());
494 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
497 // Receive two long (>128 bytes) message.
498 TEST_F(GCMConnectionHandlerImplTest
, Recv2LongMsgs
) {
499 std::string handshake_request
= EncodeHandshakeRequest();
500 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
501 handshake_request
.c_str(),
502 handshake_request
.size()));
503 std::string handshake_response
= EncodeHandshakeResponse();
505 std::string data_message_proto
=
506 BuildDataMessage(kDataMsgFromLong
, kDataMsgCategoryLong
);
507 std::string data_message_proto2
=
508 BuildDataMessage(kDataMsgFromLong2
, kDataMsgCategoryLong2
);
509 std::string data_message_pkt
=
510 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
511 data_message_pkt
+= EncodePacket(kDataMessageStanzaTag
, data_message_proto2
);
512 DCHECK_GT(data_message_pkt
.size(), 256U);
514 read_list
.push_back(net::MockRead(net::ASYNC
,
515 handshake_response
.c_str(),
516 handshake_response
.size()));
517 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
518 data_message_pkt
.c_str(),
519 data_message_pkt
.size()));
520 BuildSocket(read_list
, write_list
);
522 ScopedMessage received_message
;
523 Connect(&received_message
);
524 WaitForMessage(); // The login send.
525 WaitForMessage(); // The login response.
526 WaitForMessage(); // The first data message.
527 ASSERT_TRUE(received_message
.get());
528 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
529 received_message
.reset();
530 WaitForMessage(); // The second data message.
531 ASSERT_TRUE(received_message
.get());
532 EXPECT_EQ(data_message_proto2
, received_message
->SerializeAsString());
533 EXPECT_EQ(net::OK
, last_error());
536 // Simulate a message where the end of the data does not arrive in time and the
538 TEST_F(GCMConnectionHandlerImplTest
, ReadTimeout
) {
539 std::string handshake_request
= EncodeHandshakeRequest();
540 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
541 handshake_request
.c_str(),
542 handshake_request
.size()));
543 std::string handshake_response
= EncodeHandshakeResponse();
545 std::string data_message_proto
= BuildDataMessage(kDataMsgFrom
,
547 std::string data_message_pkt
=
548 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
549 int bytes_in_first_message
= data_message_pkt
.size() / 2;
551 read_list
.push_back(net::MockRead(net::ASYNC
,
552 handshake_response
.c_str(),
553 handshake_response
.size()));
554 read_list
.push_back(net::MockRead(net::ASYNC
,
555 data_message_pkt
.c_str(),
556 bytes_in_first_message
));
557 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
558 net::ERR_IO_PENDING
));
559 read_list
.push_back(net::MockRead(net::ASYNC
,
560 data_message_pkt
.c_str() +
561 bytes_in_first_message
,
562 data_message_pkt
.size() -
563 bytes_in_first_message
));
564 BuildSocket(read_list
, write_list
);
566 ScopedMessage received_message
;
567 Connect(&received_message
);
568 WaitForMessage(); // The login send.
569 WaitForMessage(); // The login response.
570 received_message
.reset();
571 WaitForMessage(); // Should time out.
572 EXPECT_FALSE(received_message
.get());
573 EXPECT_EQ(net::ERR_TIMED_OUT
, last_error());
574 EXPECT_FALSE(connection_handler()->CanSendMessage());
576 // Finish the socket read. Should have no effect.
577 data_provider()->ForceNextRead();
580 // Receive a message with zero data bytes.
581 TEST_F(GCMConnectionHandlerImplTest
, RecvMsgNoData
) {
582 std::string handshake_request
= EncodeHandshakeRequest();
583 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
584 handshake_request
.c_str(),
585 handshake_request
.size()));
586 std::string handshake_response
= EncodeHandshakeResponse();
588 std::string data_message_pkt
= EncodePacket(kHeartbeatPingTag
, "");
589 ASSERT_EQ(data_message_pkt
.size(), 2U);
591 read_list
.push_back(net::MockRead(net::ASYNC
,
592 handshake_response
.c_str(),
593 handshake_response
.size()));
594 read_list
.push_back(net::MockRead(net::ASYNC
,
595 data_message_pkt
.c_str(),
596 data_message_pkt
.size()));
597 BuildSocket(read_list
, write_list
);
599 ScopedMessage received_message
;
600 Connect(&received_message
);
601 WaitForMessage(); // The login send.
602 WaitForMessage(); // The login response.
603 received_message
.reset();
604 WaitForMessage(); // The heartbeat ping.
605 EXPECT_TRUE(received_message
.get());
606 EXPECT_EQ(GetMCSProtoTag(*received_message
), kHeartbeatPingTag
);
607 EXPECT_EQ(net::OK
, last_error());
608 EXPECT_TRUE(connection_handler()->CanSendMessage());
611 // Send a message after performing the handshake.
612 TEST_F(GCMConnectionHandlerImplTest
, SendMsg
) {
613 mcs_proto::DataMessageStanza data_message
;
614 data_message
.set_from(kDataMsgFrom
);
615 data_message
.set_category(kDataMsgCategory
);
616 std::string handshake_request
= EncodeHandshakeRequest();
617 std::string data_message_pkt
=
618 EncodePacket(kDataMessageStanzaTag
, data_message
.SerializeAsString());
619 WriteList write_list
;
620 write_list
.push_back(net::MockWrite(net::ASYNC
,
621 handshake_request
.c_str(),
622 handshake_request
.size()));
623 write_list
.push_back(net::MockWrite(net::ASYNC
,
624 data_message_pkt
.c_str(),
625 data_message_pkt
.size()));
626 std::string handshake_response
= EncodeHandshakeResponse();
628 read_list
.push_back(net::MockRead(net::ASYNC
,
629 handshake_response
.c_str(),
630 handshake_response
.size()));
631 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
, net::ERR_IO_PENDING
));
632 BuildSocket(read_list
, write_list
);
634 ScopedMessage received_message
;
635 Connect(&received_message
);
636 WaitForMessage(); // The login send.
637 WaitForMessage(); // The login response.
638 EXPECT_TRUE(connection_handler()->CanSendMessage());
639 connection_handler()->SendMessage(data_message
);
640 EXPECT_FALSE(connection_handler()->CanSendMessage());
641 WaitForMessage(); // The message send.
642 EXPECT_TRUE(connection_handler()->CanSendMessage());
645 // Attempt to send a message after the socket is disconnected due to a timeout.
646 TEST_F(GCMConnectionHandlerImplTest
, SendMsgSocketDisconnected
) {
647 std::string handshake_request
= EncodeHandshakeRequest();
648 WriteList write_list
;
649 write_list
.push_back(net::MockWrite(net::ASYNC
,
650 handshake_request
.c_str(),
651 handshake_request
.size()));
652 std::string handshake_response
= EncodeHandshakeResponse();
654 read_list
.push_back(net::MockRead(net::ASYNC
,
655 handshake_response
.c_str(),
656 handshake_response
.size()));
657 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
, net::ERR_IO_PENDING
));
658 net::StreamSocket
* socket
= BuildSocket(read_list
, write_list
);
660 ScopedMessage received_message
;
661 Connect(&received_message
);
662 WaitForMessage(); // The login send.
663 WaitForMessage(); // The login response.
664 EXPECT_TRUE(connection_handler()->CanSendMessage());
665 socket
->Disconnect();
666 mcs_proto::DataMessageStanza data_message
;
667 data_message
.set_from(kDataMsgFrom
);
668 data_message
.set_category(kDataMsgCategory
);
669 connection_handler()->SendMessage(data_message
);
670 EXPECT_FALSE(connection_handler()->CanSendMessage());
671 WaitForMessage(); // The message send. Should result in an error
672 EXPECT_FALSE(connection_handler()->CanSendMessage());
673 EXPECT_EQ(net::ERR_CONNECTION_CLOSED
, last_error());
676 // Receive a message whose size field was corrupted and is larger than the
677 // socket's buffer. Should fail gracefully.
678 TEST_F(GCMConnectionHandlerImplTest
, CorruptedSize
) {
679 std::string handshake_request
= EncodeHandshakeRequest();
680 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
681 handshake_request
.c_str(),
682 handshake_request
.size()));
683 std::string handshake_response
= EncodeHandshakeResponse();
685 // Fill a string with 9000 character zero.
686 std::string
data_message_proto(9000, '0');
687 std::string data_message_pkt
=
688 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
690 read_list
.push_back(net::MockRead(net::ASYNC
,
691 handshake_response
.c_str(),
692 handshake_response
.size()));
693 read_list
.push_back(net::MockRead(net::ASYNC
,
694 data_message_pkt
.c_str(),
695 data_message_pkt
.size()));
696 BuildSocket(read_list
, write_list
);
698 ScopedMessage received_message
;
699 Connect(&received_message
);
700 WaitForMessage(); // The login send.
701 WaitForMessage(); // The login response.
702 received_message
.reset();
703 WaitForMessage(); // The data message.
704 EXPECT_FALSE(received_message
.get());
705 EXPECT_EQ(net::ERR_FILE_TOO_BIG
, last_error());