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";
44 const uint8 kInvalidTag
= 100; // An invalid tag.
46 // ---- Helpers for building messages. ----
48 // Encode a protobuf packet with protobuf type |tag| and serialized protobuf
49 // bytes |proto| into the MCS message form (tag + varint size + bytes).
50 std::string
EncodePacket(uint8 tag
, const std::string
& proto
) {
52 google::protobuf::io::StringOutputStream
string_output_stream(&result
);
54 google::protobuf::io::CodedOutputStream
coded_output_stream(
55 &string_output_stream
);
56 const unsigned char tag_byte
[1] = { tag
};
57 coded_output_stream
.WriteRaw(tag_byte
, 1);
58 coded_output_stream
.WriteVarint32(proto
.size());
59 coded_output_stream
.WriteRaw(proto
.c_str(), proto
.size());
60 // ~CodedOutputStream must run before the move constructor at the
61 // return statement. http://crbug.com/338962
66 // Encode a handshake request into the MCS message form.
67 std::string
EncodeHandshakeRequest() {
69 const char version_byte
[1] = {kMCSVersion
};
70 result
.append(version_byte
, 1);
71 ScopedMessage
login_request(
72 BuildLoginRequest(kAuthId
, kAuthToken
, ""));
73 result
.append(EncodePacket(kLoginRequestTag
,
74 login_request
->SerializeAsString()));
78 // Build a serialized login response protobuf.
79 std::string
BuildLoginResponse() {
81 mcs_proto::LoginResponse login_response
;
82 login_response
.set_id("id");
83 result
.append(login_response
.SerializeAsString());
87 // Encoode a handshake response into the MCS message form.
88 std::string
EncodeHandshakeResponse() {
90 const char version_byte
[1] = {kMCSVersion
};
91 result
.append(version_byte
, 1);
92 result
.append(EncodePacket(kLoginResponseTag
, BuildLoginResponse()));
96 // Build a serialized data message stanza protobuf.
97 std::string
BuildDataMessage(const std::string
& from
,
98 const std::string
& category
) {
100 mcs_proto::DataMessageStanza data_message
;
101 data_message
.set_from(from
);
102 data_message
.set_category(category
);
103 return data_message
.SerializeAsString();
106 class GCMConnectionHandlerImplTest
: public testing::Test
{
108 GCMConnectionHandlerImplTest();
109 ~GCMConnectionHandlerImplTest() override
;
111 net::StreamSocket
* BuildSocket(const ReadList
& read_list
,
112 const WriteList
& write_list
);
114 // Pump |message_loop_|, resetting |run_loop_| after completion.
117 ConnectionHandlerImpl
* connection_handler() {
118 return connection_handler_
.get();
120 base::MessageLoop
* message_loop() { return &message_loop_
; };
121 net::StaticSocketDataProvider
* data_provider() {
122 return data_provider_
.get();
124 int last_error() const { return last_error_
; }
126 // Initialize the connection handler, setting |dst_proto| as the destination
127 // for any received messages.
128 void Connect(ScopedMessage
* dst_proto
);
130 // Runs the message loop until a message is received.
131 void WaitForMessage();
134 void ReadContinuation(ScopedMessage
* dst_proto
, ScopedMessage new_proto
);
135 void WriteContinuation();
136 void ConnectionContinuation(int error
);
138 // SocketStreams and their data provider.
139 ReadList mock_reads_
;
140 WriteList mock_writes_
;
141 scoped_ptr
<net::StaticSocketDataProvider
> data_provider_
;
143 // The connection handler being tested.
144 scoped_ptr
<ConnectionHandlerImpl
> connection_handler_
;
146 // The last connection error received.
150 scoped_ptr
<net::StreamSocket
> socket_
;
151 net::MockClientSocketFactory socket_factory_
;
152 net::AddressList address_list_
;
154 base::MessageLoopForIO message_loop_
;
155 scoped_ptr
<base::RunLoop
> run_loop_
;
158 GCMConnectionHandlerImplTest::GCMConnectionHandlerImplTest()
160 net::IPAddressNumber ip_number
;
161 net::ParseIPLiteralToNumber("127.0.0.1", &ip_number
);
162 address_list_
= net::AddressList::CreateFromIPAddress(ip_number
, kMCSPort
);
165 GCMConnectionHandlerImplTest::~GCMConnectionHandlerImplTest() {
168 net::StreamSocket
* GCMConnectionHandlerImplTest::BuildSocket(
169 const ReadList
& read_list
,
170 const WriteList
& write_list
) {
171 mock_reads_
= read_list
;
172 mock_writes_
= write_list
;
173 data_provider_
.reset(
174 new net::StaticSocketDataProvider(
175 &(mock_reads_
[0]), mock_reads_
.size(),
176 &(mock_writes_
[0]), mock_writes_
.size()));
177 socket_factory_
.AddSocketDataProvider(data_provider_
.get());
179 socket_
= socket_factory_
.CreateTransportClientSocket(
180 address_list_
, NULL
, net::NetLog::Source());
181 socket_
->Connect(net::CompletionCallback());
183 run_loop_
.reset(new base::RunLoop());
186 DCHECK(socket_
->IsConnected());
187 return socket_
.get();
190 void GCMConnectionHandlerImplTest::PumpLoop() {
191 run_loop_
->RunUntilIdle();
192 run_loop_
.reset(new base::RunLoop());
195 void GCMConnectionHandlerImplTest::Connect(
196 ScopedMessage
* dst_proto
) {
197 connection_handler_
.reset(new ConnectionHandlerImpl(
198 TestTimeouts::tiny_timeout(),
199 base::Bind(&GCMConnectionHandlerImplTest::ReadContinuation
,
200 base::Unretained(this),
202 base::Bind(&GCMConnectionHandlerImplTest::WriteContinuation
,
203 base::Unretained(this)),
204 base::Bind(&GCMConnectionHandlerImplTest::ConnectionContinuation
,
205 base::Unretained(this))));
206 EXPECT_FALSE(connection_handler()->CanSendMessage());
207 connection_handler_
->Init(
208 *BuildLoginRequest(kAuthId
, kAuthToken
, ""),
212 void GCMConnectionHandlerImplTest::ReadContinuation(
213 ScopedMessage
* dst_proto
,
214 ScopedMessage new_proto
) {
215 *dst_proto
= new_proto
.Pass();
219 void GCMConnectionHandlerImplTest::WaitForMessage() {
221 run_loop_
.reset(new base::RunLoop());
224 void GCMConnectionHandlerImplTest::WriteContinuation() {
228 void GCMConnectionHandlerImplTest::ConnectionContinuation(int error
) {
233 // Initialize the connection handler and ensure the handshake completes
235 TEST_F(GCMConnectionHandlerImplTest
, Init
) {
236 std::string handshake_request
= EncodeHandshakeRequest();
237 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
238 handshake_request
.c_str(),
239 handshake_request
.size()));
240 std::string handshake_response
= EncodeHandshakeResponse();
241 ReadList
read_list(1, net::MockRead(net::ASYNC
,
242 handshake_response
.c_str(),
243 handshake_response
.size()));
244 BuildSocket(read_list
, write_list
);
246 ScopedMessage received_message
;
247 Connect(&received_message
);
248 EXPECT_FALSE(connection_handler()->CanSendMessage());
249 WaitForMessage(); // The login send.
250 WaitForMessage(); // The login response.
251 ASSERT_TRUE(received_message
.get());
252 EXPECT_EQ(BuildLoginResponse(), received_message
->SerializeAsString());
253 EXPECT_TRUE(connection_handler()->CanSendMessage());
256 // Simulate the handshake response returning an older version. Initialization
258 TEST_F(GCMConnectionHandlerImplTest
, InitFailedVersionCheck
) {
259 std::string handshake_request
= EncodeHandshakeRequest();
260 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
261 handshake_request
.c_str(),
262 handshake_request
.size()));
263 std::string handshake_response
= EncodeHandshakeResponse();
264 // Overwrite the version byte.
265 handshake_response
[0] = 37;
266 ReadList
read_list(1, net::MockRead(net::ASYNC
,
267 handshake_response
.c_str(),
268 handshake_response
.size()));
269 BuildSocket(read_list
, write_list
);
271 ScopedMessage received_message
;
272 Connect(&received_message
);
273 WaitForMessage(); // The login send.
274 WaitForMessage(); // The login response. Should result in a connection error.
275 EXPECT_FALSE(received_message
.get());
276 EXPECT_FALSE(connection_handler()->CanSendMessage());
277 EXPECT_EQ(net::ERR_FAILED
, last_error());
280 // Attempt to initialize, but receive no server response, resulting in a time
282 TEST_F(GCMConnectionHandlerImplTest
, InitTimeout
) {
283 std::string handshake_request
= EncodeHandshakeRequest();
284 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
285 handshake_request
.c_str(),
286 handshake_request
.size()));
287 ReadList
read_list(1, net::MockRead(net::SYNCHRONOUS
,
288 net::ERR_IO_PENDING
));
289 BuildSocket(read_list
, write_list
);
291 ScopedMessage received_message
;
292 Connect(&received_message
);
293 WaitForMessage(); // The login send.
294 WaitForMessage(); // The login response. Should result in a connection error.
295 EXPECT_FALSE(received_message
.get());
296 EXPECT_FALSE(connection_handler()->CanSendMessage());
297 EXPECT_EQ(net::ERR_TIMED_OUT
, last_error());
300 // Attempt to initialize, but receive an incomplete server response, resulting
302 TEST_F(GCMConnectionHandlerImplTest
, InitIncompleteTimeout
) {
303 std::string handshake_request
= EncodeHandshakeRequest();
304 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
305 handshake_request
.c_str(),
306 handshake_request
.size()));
307 std::string handshake_response
= EncodeHandshakeResponse();
309 read_list
.push_back(net::MockRead(net::ASYNC
,
310 handshake_response
.c_str(),
311 handshake_response
.size() / 2));
312 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
313 net::ERR_IO_PENDING
));
314 BuildSocket(read_list
, write_list
);
316 ScopedMessage received_message
;
317 Connect(&received_message
);
318 WaitForMessage(); // The login send.
319 WaitForMessage(); // The login response. Should result in a connection error.
320 EXPECT_FALSE(received_message
.get());
321 EXPECT_FALSE(connection_handler()->CanSendMessage());
322 EXPECT_EQ(net::ERR_TIMED_OUT
, last_error());
325 // Reinitialize the connection handler after failing to initialize.
326 TEST_F(GCMConnectionHandlerImplTest
, ReInit
) {
327 std::string handshake_request
= EncodeHandshakeRequest();
328 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
329 handshake_request
.c_str(),
330 handshake_request
.size()));
331 ReadList
read_list(1, net::MockRead(net::SYNCHRONOUS
,
332 net::ERR_IO_PENDING
));
333 BuildSocket(read_list
, write_list
);
335 ScopedMessage received_message
;
336 Connect(&received_message
);
337 WaitForMessage(); // The login send.
338 WaitForMessage(); // The login response. Should result in a connection error.
339 EXPECT_FALSE(received_message
.get());
340 EXPECT_FALSE(connection_handler()->CanSendMessage());
341 EXPECT_EQ(net::ERR_TIMED_OUT
, last_error());
343 // Build a new socket and reconnect, successfully this time.
344 std::string handshake_response
= EncodeHandshakeResponse();
345 read_list
[0] = net::MockRead(net::ASYNC
,
346 handshake_response
.c_str(),
347 handshake_response
.size());
348 BuildSocket(read_list
, write_list
);
349 Connect(&received_message
);
350 EXPECT_FALSE(connection_handler()->CanSendMessage());
351 WaitForMessage(); // The login send.
352 WaitForMessage(); // The login response.
353 ASSERT_TRUE(received_message
.get());
354 EXPECT_EQ(BuildLoginResponse(), received_message
->SerializeAsString());
355 EXPECT_TRUE(connection_handler()->CanSendMessage());
358 // Verify that messages can be received after initialization.
359 TEST_F(GCMConnectionHandlerImplTest
, RecvMsg
) {
360 std::string handshake_request
= EncodeHandshakeRequest();
361 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
362 handshake_request
.c_str(),
363 handshake_request
.size()));
364 std::string handshake_response
= EncodeHandshakeResponse();
366 std::string data_message_proto
= BuildDataMessage(kDataMsgFrom
,
368 std::string data_message_pkt
=
369 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
371 read_list
.push_back(net::MockRead(net::ASYNC
,
372 handshake_response
.c_str(),
373 handshake_response
.size()));
374 read_list
.push_back(net::MockRead(net::ASYNC
,
375 data_message_pkt
.c_str(),
376 data_message_pkt
.size()));
377 BuildSocket(read_list
, write_list
);
379 ScopedMessage received_message
;
380 Connect(&received_message
);
381 WaitForMessage(); // The login send.
382 WaitForMessage(); // The login response.
383 WaitForMessage(); // The data message.
384 ASSERT_TRUE(received_message
.get());
385 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
386 EXPECT_EQ(net::OK
, last_error());
389 // Verify that if two messages arrive at once, they're treated appropriately.
390 TEST_F(GCMConnectionHandlerImplTest
, Recv2Msgs
) {
391 std::string handshake_request
= EncodeHandshakeRequest();
392 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
393 handshake_request
.c_str(),
394 handshake_request
.size()));
395 std::string handshake_response
= EncodeHandshakeResponse();
397 std::string data_message_proto
= BuildDataMessage(kDataMsgFrom
,
399 std::string data_message_proto2
= BuildDataMessage(kDataMsgFrom2
,
401 std::string data_message_pkt
=
402 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
403 data_message_pkt
+= EncodePacket(kDataMessageStanzaTag
, data_message_proto2
);
405 read_list
.push_back(net::MockRead(net::ASYNC
,
406 handshake_response
.c_str(),
407 handshake_response
.size()));
408 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
409 data_message_pkt
.c_str(),
410 data_message_pkt
.size()));
411 BuildSocket(read_list
, write_list
);
413 ScopedMessage received_message
;
414 Connect(&received_message
);
415 WaitForMessage(); // The login send.
416 WaitForMessage(); // The login response.
417 WaitForMessage(); // The first data message.
418 ASSERT_TRUE(received_message
.get());
419 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
420 received_message
.reset();
421 WaitForMessage(); // The second data message.
422 ASSERT_TRUE(received_message
.get());
423 EXPECT_EQ(data_message_proto2
, received_message
->SerializeAsString());
424 EXPECT_EQ(net::OK
, last_error());
427 // Receive a long (>128 bytes) message.
428 TEST_F(GCMConnectionHandlerImplTest
, RecvLongMsg
) {
429 std::string handshake_request
= EncodeHandshakeRequest();
430 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
431 handshake_request
.c_str(),
432 handshake_request
.size()));
433 std::string handshake_response
= EncodeHandshakeResponse();
435 std::string data_message_proto
=
436 BuildDataMessage(kDataMsgFromLong
, kDataMsgCategoryLong
);
437 std::string data_message_pkt
=
438 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
439 DCHECK_GT(data_message_pkt
.size(), 128U);
441 read_list
.push_back(net::MockRead(net::ASYNC
,
442 handshake_response
.c_str(),
443 handshake_response
.size()));
444 read_list
.push_back(net::MockRead(net::ASYNC
,
445 data_message_pkt
.c_str(),
446 data_message_pkt
.size()));
447 BuildSocket(read_list
, write_list
);
449 ScopedMessage received_message
;
450 Connect(&received_message
);
451 WaitForMessage(); // The login send.
452 WaitForMessage(); // The login response.
453 WaitForMessage(); // The data message.
454 ASSERT_TRUE(received_message
.get());
455 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
456 EXPECT_EQ(net::OK
, last_error());
459 // Receive a long (>128 bytes) message in two synchronous parts.
460 TEST_F(GCMConnectionHandlerImplTest
, RecvLongMsg2Parts
) {
461 std::string handshake_request
= EncodeHandshakeRequest();
462 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
463 handshake_request
.c_str(),
464 handshake_request
.size()));
465 std::string handshake_response
= EncodeHandshakeResponse();
467 std::string data_message_proto
=
468 BuildDataMessage(kDataMsgFromLong
, kDataMsgCategoryLong
);
469 std::string data_message_pkt
=
470 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
471 DCHECK_GT(data_message_pkt
.size(), 128U);
473 read_list
.push_back(net::MockRead(net::ASYNC
,
474 handshake_response
.c_str(),
475 handshake_response
.size()));
477 int bytes_in_first_message
= data_message_pkt
.size() / 2;
478 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
479 data_message_pkt
.c_str(),
480 bytes_in_first_message
));
481 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
482 data_message_pkt
.c_str() +
483 bytes_in_first_message
,
484 data_message_pkt
.size() -
485 bytes_in_first_message
));
486 BuildSocket(read_list
, write_list
);
488 ScopedMessage received_message
;
489 Connect(&received_message
);
490 WaitForMessage(); // The login send.
491 WaitForMessage(); // The login response.
492 WaitForMessage(); // The data message.
493 ASSERT_TRUE(received_message
.get());
494 EXPECT_EQ(net::OK
, last_error());
495 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
498 // Receive two long (>128 bytes) message.
499 TEST_F(GCMConnectionHandlerImplTest
, Recv2LongMsgs
) {
500 std::string handshake_request
= EncodeHandshakeRequest();
501 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
502 handshake_request
.c_str(),
503 handshake_request
.size()));
504 std::string handshake_response
= EncodeHandshakeResponse();
506 std::string data_message_proto
=
507 BuildDataMessage(kDataMsgFromLong
, kDataMsgCategoryLong
);
508 std::string data_message_proto2
=
509 BuildDataMessage(kDataMsgFromLong2
, kDataMsgCategoryLong2
);
510 std::string data_message_pkt
=
511 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
512 data_message_pkt
+= EncodePacket(kDataMessageStanzaTag
, data_message_proto2
);
513 DCHECK_GT(data_message_pkt
.size(), 256U);
515 read_list
.push_back(net::MockRead(net::ASYNC
,
516 handshake_response
.c_str(),
517 handshake_response
.size()));
518 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
519 data_message_pkt
.c_str(),
520 data_message_pkt
.size()));
521 BuildSocket(read_list
, write_list
);
523 ScopedMessage received_message
;
524 Connect(&received_message
);
525 WaitForMessage(); // The login send.
526 WaitForMessage(); // The login response.
527 WaitForMessage(); // The first data message.
528 ASSERT_TRUE(received_message
.get());
529 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
530 received_message
.reset();
531 WaitForMessage(); // The second data message.
532 ASSERT_TRUE(received_message
.get());
533 EXPECT_EQ(data_message_proto2
, received_message
->SerializeAsString());
534 EXPECT_EQ(net::OK
, last_error());
537 // Simulate a message where the end of the data does not arrive in time and the
539 TEST_F(GCMConnectionHandlerImplTest
, ReadTimeout
) {
540 std::string handshake_request
= EncodeHandshakeRequest();
541 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
542 handshake_request
.c_str(),
543 handshake_request
.size()));
544 std::string handshake_response
= EncodeHandshakeResponse();
546 std::string data_message_proto
= BuildDataMessage(kDataMsgFrom
,
548 std::string data_message_pkt
=
549 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
550 int bytes_in_first_message
= data_message_pkt
.size() / 2;
552 read_list
.push_back(net::MockRead(net::ASYNC
,
553 handshake_response
.c_str(),
554 handshake_response
.size()));
555 read_list
.push_back(net::MockRead(net::ASYNC
,
556 data_message_pkt
.c_str(),
557 bytes_in_first_message
));
558 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
559 net::ERR_IO_PENDING
));
560 read_list
.push_back(net::MockRead(net::ASYNC
,
561 data_message_pkt
.c_str() +
562 bytes_in_first_message
,
563 data_message_pkt
.size() -
564 bytes_in_first_message
));
565 BuildSocket(read_list
, write_list
);
567 ScopedMessage received_message
;
568 Connect(&received_message
);
569 WaitForMessage(); // The login send.
570 WaitForMessage(); // The login response.
571 received_message
.reset();
572 WaitForMessage(); // Should time out.
573 EXPECT_FALSE(received_message
.get());
574 EXPECT_EQ(net::ERR_TIMED_OUT
, last_error());
575 EXPECT_FALSE(connection_handler()->CanSendMessage());
578 // Receive a message with zero data bytes.
579 TEST_F(GCMConnectionHandlerImplTest
, RecvMsgNoData
) {
580 std::string handshake_request
= EncodeHandshakeRequest();
581 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
582 handshake_request
.c_str(),
583 handshake_request
.size()));
584 std::string handshake_response
= EncodeHandshakeResponse();
586 std::string data_message_pkt
= EncodePacket(kHeartbeatPingTag
, "");
587 ASSERT_EQ(data_message_pkt
.size(), 2U);
589 read_list
.push_back(net::MockRead(net::ASYNC
,
590 handshake_response
.c_str(),
591 handshake_response
.size()));
592 read_list
.push_back(net::MockRead(net::ASYNC
,
593 data_message_pkt
.c_str(),
594 data_message_pkt
.size()));
595 BuildSocket(read_list
, write_list
);
597 ScopedMessage received_message
;
598 Connect(&received_message
);
599 WaitForMessage(); // The login send.
600 WaitForMessage(); // The login response.
601 received_message
.reset();
602 WaitForMessage(); // The heartbeat ping.
603 EXPECT_TRUE(received_message
.get());
604 EXPECT_EQ(GetMCSProtoTag(*received_message
), kHeartbeatPingTag
);
605 EXPECT_EQ(net::OK
, last_error());
606 EXPECT_TRUE(connection_handler()->CanSendMessage());
609 // Send a message after performing the handshake.
610 TEST_F(GCMConnectionHandlerImplTest
, SendMsg
) {
611 mcs_proto::DataMessageStanza data_message
;
612 data_message
.set_from(kDataMsgFrom
);
613 data_message
.set_category(kDataMsgCategory
);
614 std::string handshake_request
= EncodeHandshakeRequest();
615 std::string data_message_pkt
=
616 EncodePacket(kDataMessageStanzaTag
, data_message
.SerializeAsString());
617 WriteList write_list
;
618 write_list
.push_back(net::MockWrite(net::ASYNC
,
619 handshake_request
.c_str(),
620 handshake_request
.size()));
621 write_list
.push_back(net::MockWrite(net::ASYNC
,
622 data_message_pkt
.c_str(),
623 data_message_pkt
.size()));
624 std::string handshake_response
= EncodeHandshakeResponse();
626 read_list
.push_back(net::MockRead(net::ASYNC
,
627 handshake_response
.c_str(),
628 handshake_response
.size()));
629 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
, net::ERR_IO_PENDING
));
630 BuildSocket(read_list
, write_list
);
632 ScopedMessage received_message
;
633 Connect(&received_message
);
634 WaitForMessage(); // The login send.
635 WaitForMessage(); // The login response.
636 EXPECT_TRUE(connection_handler()->CanSendMessage());
637 connection_handler()->SendMessage(data_message
);
638 EXPECT_FALSE(connection_handler()->CanSendMessage());
639 WaitForMessage(); // The message send.
640 EXPECT_TRUE(connection_handler()->CanSendMessage());
643 // Attempt to send a message after the socket is disconnected due to a timeout.
644 TEST_F(GCMConnectionHandlerImplTest
, SendMsgSocketDisconnected
) {
645 std::string handshake_request
= EncodeHandshakeRequest();
646 WriteList write_list
;
647 write_list
.push_back(net::MockWrite(net::ASYNC
,
648 handshake_request
.c_str(),
649 handshake_request
.size()));
650 std::string handshake_response
= EncodeHandshakeResponse();
652 read_list
.push_back(net::MockRead(net::ASYNC
,
653 handshake_response
.c_str(),
654 handshake_response
.size()));
655 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
, net::ERR_IO_PENDING
));
656 net::StreamSocket
* socket
= BuildSocket(read_list
, write_list
);
658 ScopedMessage received_message
;
659 Connect(&received_message
);
660 WaitForMessage(); // The login send.
661 WaitForMessage(); // The login response.
662 EXPECT_TRUE(connection_handler()->CanSendMessage());
663 socket
->Disconnect();
664 mcs_proto::DataMessageStanza data_message
;
665 data_message
.set_from(kDataMsgFrom
);
666 data_message
.set_category(kDataMsgCategory
);
667 connection_handler()->SendMessage(data_message
);
668 EXPECT_FALSE(connection_handler()->CanSendMessage());
669 WaitForMessage(); // The message send. Should result in an error
670 EXPECT_FALSE(connection_handler()->CanSendMessage());
671 EXPECT_EQ(net::ERR_CONNECTION_CLOSED
, last_error());
674 // Receive a message with a custom data packet that is larger than the
675 // default data limit (and the socket buffer limit). Should successfully
676 // read the packet by using the in-memory buffer.
677 TEST_F(GCMConnectionHandlerImplTest
, ExtraLargeDataPacket
) {
678 std::string handshake_request
= EncodeHandshakeRequest();
679 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
680 handshake_request
.c_str(),
681 handshake_request
.size()));
682 std::string handshake_response
= EncodeHandshakeResponse();
684 const std::string
kVeryLongFrom(20000, '0');
685 std::string data_message_proto
= BuildDataMessage(kVeryLongFrom
,
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 WaitForMessage(); // The data message.
703 ASSERT_TRUE(received_message
.get());
704 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
705 EXPECT_EQ(net::OK
, last_error());
708 // Receive two messages with a custom data packet that is larger than the
709 // default data limit (and the socket buffer limit). Should successfully
710 // read the packet by using the in-memory buffer.
711 TEST_F(GCMConnectionHandlerImplTest
, 2ExtraLargeDataPacketMsgs
) {
712 std::string handshake_request
= EncodeHandshakeRequest();
713 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
714 handshake_request
.c_str(),
715 handshake_request
.size()));
716 std::string handshake_response
= EncodeHandshakeResponse();
718 const std::string
kVeryLongFrom(20000, '0');
719 std::string data_message_proto
= BuildDataMessage(kVeryLongFrom
,
721 std::string data_message_pkt
=
722 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
724 read_list
.push_back(net::MockRead(net::ASYNC
,
725 handshake_response
.c_str(),
726 handshake_response
.size()));
727 read_list
.push_back(net::MockRead(net::ASYNC
,
728 data_message_pkt
.c_str(),
729 data_message_pkt
.size()));
730 read_list
.push_back(net::MockRead(net::SYNCHRONOUS
,
731 data_message_pkt
.c_str(),
732 data_message_pkt
.size()));
733 BuildSocket(read_list
, write_list
);
735 ScopedMessage received_message
;
736 Connect(&received_message
);
737 WaitForMessage(); // The login send.
738 WaitForMessage(); // The login response.
739 WaitForMessage(); // The data message.
740 ASSERT_TRUE(received_message
.get());
741 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
742 EXPECT_EQ(net::OK
, last_error());
743 received_message
.reset();
744 WaitForMessage(); // The second data message.
745 ASSERT_TRUE(received_message
.get());
746 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
747 EXPECT_EQ(net::OK
, last_error());
750 // Make sure a message with an invalid tag is handled gracefully and resets
751 // the connection with an invalid argument error.
752 TEST_F(GCMConnectionHandlerImplTest
, InvalidTag
) {
753 std::string handshake_request
= EncodeHandshakeRequest();
754 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
755 handshake_request
.c_str(),
756 handshake_request
.size()));
757 std::string handshake_response
= EncodeHandshakeResponse();
759 std::string invalid_message
= "0";
760 std::string invalid_message_pkt
=
761 EncodePacket(kInvalidTag
, invalid_message
);
763 read_list
.push_back(net::MockRead(net::ASYNC
,
764 handshake_response
.c_str(),
765 handshake_response
.size()));
766 read_list
.push_back(net::MockRead(net::ASYNC
,
767 invalid_message_pkt
.c_str(),
768 invalid_message_pkt
.size()));
769 BuildSocket(read_list
, write_list
);
771 ScopedMessage received_message
;
772 Connect(&received_message
);
773 WaitForMessage(); // The login send.
774 WaitForMessage(); // The login response.
775 received_message
.reset();
776 WaitForMessage(); // The invalid message.
777 EXPECT_FALSE(received_message
.get());
778 EXPECT_EQ(net::ERR_INVALID_ARGUMENT
, last_error());
781 // Receive a message where the size field spans two socket reads.
782 TEST_F(GCMConnectionHandlerImplTest
, RecvMsgSplitSize
) {
783 std::string handshake_request
= EncodeHandshakeRequest();
784 WriteList
write_list(1, net::MockWrite(net::ASYNC
,
785 handshake_request
.c_str(),
786 handshake_request
.size()));
787 std::string handshake_response
= EncodeHandshakeResponse();
789 std::string data_message_proto
=
790 BuildDataMessage(kDataMsgFromLong
, kDataMsgCategoryLong
);
791 std::string data_message_pkt
=
792 EncodePacket(kDataMessageStanzaTag
, data_message_proto
);
793 DCHECK_GT(data_message_pkt
.size(), 128U);
795 read_list
.push_back(net::MockRead(net::ASYNC
,
796 handshake_response
.c_str(),
797 handshake_response
.size()));
798 // The first two bytes are the tag byte and the first byte of the size packet.
799 read_list
.push_back(net::MockRead(net::ASYNC
,
800 data_message_pkt
.c_str(),
802 // Start from the second byte of the size packet.
803 read_list
.push_back(net::MockRead(net::ASYNC
,
804 data_message_pkt
.c_str() + 2,
805 data_message_pkt
.size() - 2));
806 BuildSocket(read_list
, write_list
);
808 ScopedMessage received_message
;
809 Connect(&received_message
);
810 WaitForMessage(); // The login send.
811 WaitForMessage(); // The login response.
812 WaitForMessage(); // The data message.
813 ASSERT_TRUE(received_message
.get());
814 EXPECT_EQ(data_message_proto
, received_message
->SerializeAsString());
815 EXPECT_EQ(net::OK
, last_error());