Mechanical rename of tracing includes for /ppapi
[chromium-blink-merge.git] / google_apis / gcm / engine / connection_handler_impl_unittest.cc
blobaaf19fcb728d066f1873a59870e9d790cea87616
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"
7 #include "base/bind.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"
21 namespace gcm {
22 namespace {
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) {
51 std::string result;
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
63 return result;
66 // Encode a handshake request into the MCS message form.
67 std::string EncodeHandshakeRequest() {
68 std::string result;
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()));
75 return result;
78 // Build a serialized login response protobuf.
79 std::string BuildLoginResponse() {
80 std::string result;
81 mcs_proto::LoginResponse login_response;
82 login_response.set_id("id");
83 result.append(login_response.SerializeAsString());
84 return result;
87 // Encoode a handshake response into the MCS message form.
88 std::string EncodeHandshakeResponse() {
89 std::string result;
90 const char version_byte[1] = {kMCSVersion};
91 result.append(version_byte, 1);
92 result.append(EncodePacket(kLoginResponseTag, BuildLoginResponse()));
93 return result;
96 // Build a serialized data message stanza protobuf.
97 std::string BuildDataMessage(const std::string& from,
98 const std::string& category) {
99 std::string result;
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 {
107 public:
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.
115 void PumpLoop();
117 ConnectionHandlerImpl* connection_handler() {
118 return connection_handler_.get();
120 base::MessageLoop* message_loop() { return &message_loop_; };
121 net::DelayedSocketData* data_provider() { return data_provider_.get(); }
122 int last_error() const { return last_error_; }
124 // Initialize the connection handler, setting |dst_proto| as the destination
125 // for any received messages.
126 void Connect(ScopedMessage* dst_proto);
128 // Runs the message loop until a message is received.
129 void WaitForMessage();
131 private:
132 void ReadContinuation(ScopedMessage* dst_proto, ScopedMessage new_proto);
133 void WriteContinuation();
134 void ConnectionContinuation(int error);
136 // SocketStreams and their data provider.
137 ReadList mock_reads_;
138 WriteList mock_writes_;
139 scoped_ptr<net::DelayedSocketData> data_provider_;
141 // The connection handler being tested.
142 scoped_ptr<ConnectionHandlerImpl> connection_handler_;
144 // The last connection error received.
145 int last_error_;
147 // net:: components.
148 scoped_ptr<net::StreamSocket> socket_;
149 net::MockClientSocketFactory socket_factory_;
150 net::AddressList address_list_;
152 base::MessageLoopForIO message_loop_;
153 scoped_ptr<base::RunLoop> run_loop_;
156 GCMConnectionHandlerImplTest::GCMConnectionHandlerImplTest()
157 : last_error_(0) {
158 net::IPAddressNumber ip_number;
159 net::ParseIPLiteralToNumber("127.0.0.1", &ip_number);
160 address_list_ = net::AddressList::CreateFromIPAddress(ip_number, kMCSPort);
163 GCMConnectionHandlerImplTest::~GCMConnectionHandlerImplTest() {
166 net::StreamSocket* GCMConnectionHandlerImplTest::BuildSocket(
167 const ReadList& read_list,
168 const WriteList& write_list) {
169 mock_reads_ = read_list;
170 mock_writes_ = write_list;
171 data_provider_.reset(
172 new net::DelayedSocketData(0,
173 &(mock_reads_[0]), mock_reads_.size(),
174 &(mock_writes_[0]), mock_writes_.size()));
175 socket_factory_.AddSocketDataProvider(data_provider_.get());
177 socket_ = socket_factory_.CreateTransportClientSocket(
178 address_list_, NULL, net::NetLog::Source());
179 socket_->Connect(net::CompletionCallback());
181 run_loop_.reset(new base::RunLoop());
182 PumpLoop();
184 DCHECK(socket_->IsConnected());
185 return socket_.get();
188 void GCMConnectionHandlerImplTest::PumpLoop() {
189 run_loop_->RunUntilIdle();
190 run_loop_.reset(new base::RunLoop());
193 void GCMConnectionHandlerImplTest::Connect(
194 ScopedMessage* dst_proto) {
195 connection_handler_.reset(new ConnectionHandlerImpl(
196 TestTimeouts::tiny_timeout(),
197 base::Bind(&GCMConnectionHandlerImplTest::ReadContinuation,
198 base::Unretained(this),
199 dst_proto),
200 base::Bind(&GCMConnectionHandlerImplTest::WriteContinuation,
201 base::Unretained(this)),
202 base::Bind(&GCMConnectionHandlerImplTest::ConnectionContinuation,
203 base::Unretained(this))));
204 EXPECT_FALSE(connection_handler()->CanSendMessage());
205 connection_handler_->Init(
206 *BuildLoginRequest(kAuthId, kAuthToken, ""),
207 socket_.get());
210 void GCMConnectionHandlerImplTest::ReadContinuation(
211 ScopedMessage* dst_proto,
212 ScopedMessage new_proto) {
213 *dst_proto = new_proto.Pass();
214 run_loop_->Quit();
217 void GCMConnectionHandlerImplTest::WaitForMessage() {
218 run_loop_->Run();
219 run_loop_.reset(new base::RunLoop());
222 void GCMConnectionHandlerImplTest::WriteContinuation() {
223 run_loop_->Quit();
226 void GCMConnectionHandlerImplTest::ConnectionContinuation(int error) {
227 last_error_ = error;
228 run_loop_->Quit();
231 // Initialize the connection handler and ensure the handshake completes
232 // successfully.
233 TEST_F(GCMConnectionHandlerImplTest, Init) {
234 std::string handshake_request = EncodeHandshakeRequest();
235 WriteList write_list(1, net::MockWrite(net::ASYNC,
236 handshake_request.c_str(),
237 handshake_request.size()));
238 std::string handshake_response = EncodeHandshakeResponse();
239 ReadList read_list(1, net::MockRead(net::ASYNC,
240 handshake_response.c_str(),
241 handshake_response.size()));
242 BuildSocket(read_list, write_list);
244 ScopedMessage received_message;
245 Connect(&received_message);
246 EXPECT_FALSE(connection_handler()->CanSendMessage());
247 WaitForMessage(); // The login send.
248 WaitForMessage(); // The login response.
249 ASSERT_TRUE(received_message.get());
250 EXPECT_EQ(BuildLoginResponse(), received_message->SerializeAsString());
251 EXPECT_TRUE(connection_handler()->CanSendMessage());
254 // Simulate the handshake response returning an older version. Initialization
255 // should fail.
256 TEST_F(GCMConnectionHandlerImplTest, InitFailedVersionCheck) {
257 std::string handshake_request = EncodeHandshakeRequest();
258 WriteList write_list(1, net::MockWrite(net::ASYNC,
259 handshake_request.c_str(),
260 handshake_request.size()));
261 std::string handshake_response = EncodeHandshakeResponse();
262 // Overwrite the version byte.
263 handshake_response[0] = 37;
264 ReadList read_list(1, net::MockRead(net::ASYNC,
265 handshake_response.c_str(),
266 handshake_response.size()));
267 BuildSocket(read_list, write_list);
269 ScopedMessage received_message;
270 Connect(&received_message);
271 WaitForMessage(); // The login send.
272 WaitForMessage(); // The login response. Should result in a connection error.
273 EXPECT_FALSE(received_message.get());
274 EXPECT_FALSE(connection_handler()->CanSendMessage());
275 EXPECT_EQ(net::ERR_FAILED, last_error());
278 // Attempt to initialize, but receive no server response, resulting in a time
279 // out.
280 TEST_F(GCMConnectionHandlerImplTest, InitTimeout) {
281 std::string handshake_request = EncodeHandshakeRequest();
282 WriteList write_list(1, net::MockWrite(net::ASYNC,
283 handshake_request.c_str(),
284 handshake_request.size()));
285 ReadList read_list(1, net::MockRead(net::SYNCHRONOUS,
286 net::ERR_IO_PENDING));
287 BuildSocket(read_list, write_list);
289 ScopedMessage received_message;
290 Connect(&received_message);
291 WaitForMessage(); // The login send.
292 WaitForMessage(); // The login response. Should result in a connection error.
293 EXPECT_FALSE(received_message.get());
294 EXPECT_FALSE(connection_handler()->CanSendMessage());
295 EXPECT_EQ(net::ERR_TIMED_OUT, last_error());
298 // Attempt to initialize, but receive an incomplete server response, resulting
299 // in a time out.
300 TEST_F(GCMConnectionHandlerImplTest, InitIncompleteTimeout) {
301 std::string handshake_request = EncodeHandshakeRequest();
302 WriteList write_list(1, net::MockWrite(net::ASYNC,
303 handshake_request.c_str(),
304 handshake_request.size()));
305 std::string handshake_response = EncodeHandshakeResponse();
306 ReadList read_list;
307 read_list.push_back(net::MockRead(net::ASYNC,
308 handshake_response.c_str(),
309 handshake_response.size() / 2));
310 read_list.push_back(net::MockRead(net::SYNCHRONOUS,
311 net::ERR_IO_PENDING));
312 BuildSocket(read_list, write_list);
314 ScopedMessage received_message;
315 Connect(&received_message);
316 WaitForMessage(); // The login send.
317 WaitForMessage(); // The login response. Should result in a connection error.
318 EXPECT_FALSE(received_message.get());
319 EXPECT_FALSE(connection_handler()->CanSendMessage());
320 EXPECT_EQ(net::ERR_TIMED_OUT, last_error());
323 // Reinitialize the connection handler after failing to initialize.
324 TEST_F(GCMConnectionHandlerImplTest, ReInit) {
325 std::string handshake_request = EncodeHandshakeRequest();
326 WriteList write_list(1, net::MockWrite(net::ASYNC,
327 handshake_request.c_str(),
328 handshake_request.size()));
329 ReadList read_list(1, net::MockRead(net::SYNCHRONOUS,
330 net::ERR_IO_PENDING));
331 BuildSocket(read_list, write_list);
333 ScopedMessage received_message;
334 Connect(&received_message);
335 WaitForMessage(); // The login send.
336 WaitForMessage(); // The login response. Should result in a connection error.
337 EXPECT_FALSE(received_message.get());
338 EXPECT_FALSE(connection_handler()->CanSendMessage());
339 EXPECT_EQ(net::ERR_TIMED_OUT, last_error());
341 // Build a new socket and reconnect, successfully this time.
342 std::string handshake_response = EncodeHandshakeResponse();
343 read_list[0] = net::MockRead(net::ASYNC,
344 handshake_response.c_str(),
345 handshake_response.size());
346 BuildSocket(read_list, write_list);
347 Connect(&received_message);
348 EXPECT_FALSE(connection_handler()->CanSendMessage());
349 WaitForMessage(); // The login send.
350 WaitForMessage(); // The login response.
351 ASSERT_TRUE(received_message.get());
352 EXPECT_EQ(BuildLoginResponse(), received_message->SerializeAsString());
353 EXPECT_TRUE(connection_handler()->CanSendMessage());
356 // Verify that messages can be received after initialization.
357 TEST_F(GCMConnectionHandlerImplTest, RecvMsg) {
358 std::string handshake_request = EncodeHandshakeRequest();
359 WriteList write_list(1, net::MockWrite(net::ASYNC,
360 handshake_request.c_str(),
361 handshake_request.size()));
362 std::string handshake_response = EncodeHandshakeResponse();
364 std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
365 kDataMsgCategory);
366 std::string data_message_pkt =
367 EncodePacket(kDataMessageStanzaTag, data_message_proto);
368 ReadList read_list;
369 read_list.push_back(net::MockRead(net::ASYNC,
370 handshake_response.c_str(),
371 handshake_response.size()));
372 read_list.push_back(net::MockRead(net::ASYNC,
373 data_message_pkt.c_str(),
374 data_message_pkt.size()));
375 BuildSocket(read_list, write_list);
377 ScopedMessage received_message;
378 Connect(&received_message);
379 WaitForMessage(); // The login send.
380 WaitForMessage(); // The login response.
381 WaitForMessage(); // The data message.
382 ASSERT_TRUE(received_message.get());
383 EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
384 EXPECT_EQ(net::OK, last_error());
387 // Verify that if two messages arrive at once, they're treated appropriately.
388 TEST_F(GCMConnectionHandlerImplTest, Recv2Msgs) {
389 std::string handshake_request = EncodeHandshakeRequest();
390 WriteList write_list(1, net::MockWrite(net::ASYNC,
391 handshake_request.c_str(),
392 handshake_request.size()));
393 std::string handshake_response = EncodeHandshakeResponse();
395 std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
396 kDataMsgCategory);
397 std::string data_message_proto2 = BuildDataMessage(kDataMsgFrom2,
398 kDataMsgCategory2);
399 std::string data_message_pkt =
400 EncodePacket(kDataMessageStanzaTag, data_message_proto);
401 data_message_pkt += EncodePacket(kDataMessageStanzaTag, data_message_proto2);
402 ReadList read_list;
403 read_list.push_back(net::MockRead(net::ASYNC,
404 handshake_response.c_str(),
405 handshake_response.size()));
406 read_list.push_back(net::MockRead(net::SYNCHRONOUS,
407 data_message_pkt.c_str(),
408 data_message_pkt.size()));
409 BuildSocket(read_list, write_list);
411 ScopedMessage received_message;
412 Connect(&received_message);
413 WaitForMessage(); // The login send.
414 WaitForMessage(); // The login response.
415 WaitForMessage(); // The first data message.
416 ASSERT_TRUE(received_message.get());
417 EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
418 received_message.reset();
419 WaitForMessage(); // The second data message.
420 ASSERT_TRUE(received_message.get());
421 EXPECT_EQ(data_message_proto2, received_message->SerializeAsString());
422 EXPECT_EQ(net::OK, last_error());
425 // Receive a long (>128 bytes) message.
426 TEST_F(GCMConnectionHandlerImplTest, RecvLongMsg) {
427 std::string handshake_request = EncodeHandshakeRequest();
428 WriteList write_list(1, net::MockWrite(net::ASYNC,
429 handshake_request.c_str(),
430 handshake_request.size()));
431 std::string handshake_response = EncodeHandshakeResponse();
433 std::string data_message_proto =
434 BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
435 std::string data_message_pkt =
436 EncodePacket(kDataMessageStanzaTag, data_message_proto);
437 DCHECK_GT(data_message_pkt.size(), 128U);
438 ReadList read_list;
439 read_list.push_back(net::MockRead(net::ASYNC,
440 handshake_response.c_str(),
441 handshake_response.size()));
442 read_list.push_back(net::MockRead(net::ASYNC,
443 data_message_pkt.c_str(),
444 data_message_pkt.size()));
445 BuildSocket(read_list, write_list);
447 ScopedMessage received_message;
448 Connect(&received_message);
449 WaitForMessage(); // The login send.
450 WaitForMessage(); // The login response.
451 WaitForMessage(); // The data message.
452 ASSERT_TRUE(received_message.get());
453 EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
454 EXPECT_EQ(net::OK, last_error());
457 // Receive a long (>128 bytes) message in two synchronous parts.
458 TEST_F(GCMConnectionHandlerImplTest, RecvLongMsg2Parts) {
459 std::string handshake_request = EncodeHandshakeRequest();
460 WriteList write_list(1, net::MockWrite(net::ASYNC,
461 handshake_request.c_str(),
462 handshake_request.size()));
463 std::string handshake_response = EncodeHandshakeResponse();
465 std::string data_message_proto =
466 BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
467 std::string data_message_pkt =
468 EncodePacket(kDataMessageStanzaTag, data_message_proto);
469 DCHECK_GT(data_message_pkt.size(), 128U);
470 ReadList read_list;
471 read_list.push_back(net::MockRead(net::ASYNC,
472 handshake_response.c_str(),
473 handshake_response.size()));
475 int bytes_in_first_message = data_message_pkt.size() / 2;
476 read_list.push_back(net::MockRead(net::SYNCHRONOUS,
477 data_message_pkt.c_str(),
478 bytes_in_first_message));
479 read_list.push_back(net::MockRead(net::SYNCHRONOUS,
480 data_message_pkt.c_str() +
481 bytes_in_first_message,
482 data_message_pkt.size() -
483 bytes_in_first_message));
484 BuildSocket(read_list, write_list);
486 ScopedMessage received_message;
487 Connect(&received_message);
488 WaitForMessage(); // The login send.
489 WaitForMessage(); // The login response.
490 WaitForMessage(); // The data message.
491 ASSERT_TRUE(received_message.get());
492 EXPECT_EQ(net::OK, last_error());
493 EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
496 // Receive two long (>128 bytes) message.
497 TEST_F(GCMConnectionHandlerImplTest, Recv2LongMsgs) {
498 std::string handshake_request = EncodeHandshakeRequest();
499 WriteList write_list(1, net::MockWrite(net::ASYNC,
500 handshake_request.c_str(),
501 handshake_request.size()));
502 std::string handshake_response = EncodeHandshakeResponse();
504 std::string data_message_proto =
505 BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
506 std::string data_message_proto2 =
507 BuildDataMessage(kDataMsgFromLong2, kDataMsgCategoryLong2);
508 std::string data_message_pkt =
509 EncodePacket(kDataMessageStanzaTag, data_message_proto);
510 data_message_pkt += EncodePacket(kDataMessageStanzaTag, data_message_proto2);
511 DCHECK_GT(data_message_pkt.size(), 256U);
512 ReadList read_list;
513 read_list.push_back(net::MockRead(net::ASYNC,
514 handshake_response.c_str(),
515 handshake_response.size()));
516 read_list.push_back(net::MockRead(net::SYNCHRONOUS,
517 data_message_pkt.c_str(),
518 data_message_pkt.size()));
519 BuildSocket(read_list, write_list);
521 ScopedMessage received_message;
522 Connect(&received_message);
523 WaitForMessage(); // The login send.
524 WaitForMessage(); // The login response.
525 WaitForMessage(); // The first data message.
526 ASSERT_TRUE(received_message.get());
527 EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
528 received_message.reset();
529 WaitForMessage(); // The second data message.
530 ASSERT_TRUE(received_message.get());
531 EXPECT_EQ(data_message_proto2, received_message->SerializeAsString());
532 EXPECT_EQ(net::OK, last_error());
535 // Simulate a message where the end of the data does not arrive in time and the
536 // read times out.
537 TEST_F(GCMConnectionHandlerImplTest, ReadTimeout) {
538 std::string handshake_request = EncodeHandshakeRequest();
539 WriteList write_list(1, net::MockWrite(net::ASYNC,
540 handshake_request.c_str(),
541 handshake_request.size()));
542 std::string handshake_response = EncodeHandshakeResponse();
544 std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
545 kDataMsgCategory);
546 std::string data_message_pkt =
547 EncodePacket(kDataMessageStanzaTag, data_message_proto);
548 int bytes_in_first_message = data_message_pkt.size() / 2;
549 ReadList read_list;
550 read_list.push_back(net::MockRead(net::ASYNC,
551 handshake_response.c_str(),
552 handshake_response.size()));
553 read_list.push_back(net::MockRead(net::ASYNC,
554 data_message_pkt.c_str(),
555 bytes_in_first_message));
556 read_list.push_back(net::MockRead(net::SYNCHRONOUS,
557 net::ERR_IO_PENDING));
558 read_list.push_back(net::MockRead(net::ASYNC,
559 data_message_pkt.c_str() +
560 bytes_in_first_message,
561 data_message_pkt.size() -
562 bytes_in_first_message));
563 BuildSocket(read_list, write_list);
565 ScopedMessage received_message;
566 Connect(&received_message);
567 WaitForMessage(); // The login send.
568 WaitForMessage(); // The login response.
569 received_message.reset();
570 WaitForMessage(); // Should time out.
571 EXPECT_FALSE(received_message.get());
572 EXPECT_EQ(net::ERR_TIMED_OUT, last_error());
573 EXPECT_FALSE(connection_handler()->CanSendMessage());
575 // Finish the socket read. Should have no effect.
576 data_provider()->ForceNextRead();
579 // Receive a message with zero data bytes.
580 TEST_F(GCMConnectionHandlerImplTest, RecvMsgNoData) {
581 std::string handshake_request = EncodeHandshakeRequest();
582 WriteList write_list(1, net::MockWrite(net::ASYNC,
583 handshake_request.c_str(),
584 handshake_request.size()));
585 std::string handshake_response = EncodeHandshakeResponse();
587 std::string data_message_pkt = EncodePacket(kHeartbeatPingTag, "");
588 ASSERT_EQ(data_message_pkt.size(), 2U);
589 ReadList read_list;
590 read_list.push_back(net::MockRead(net::ASYNC,
591 handshake_response.c_str(),
592 handshake_response.size()));
593 read_list.push_back(net::MockRead(net::ASYNC,
594 data_message_pkt.c_str(),
595 data_message_pkt.size()));
596 BuildSocket(read_list, write_list);
598 ScopedMessage received_message;
599 Connect(&received_message);
600 WaitForMessage(); // The login send.
601 WaitForMessage(); // The login response.
602 received_message.reset();
603 WaitForMessage(); // The heartbeat ping.
604 EXPECT_TRUE(received_message.get());
605 EXPECT_EQ(GetMCSProtoTag(*received_message), kHeartbeatPingTag);
606 EXPECT_EQ(net::OK, last_error());
607 EXPECT_TRUE(connection_handler()->CanSendMessage());
610 // Send a message after performing the handshake.
611 TEST_F(GCMConnectionHandlerImplTest, SendMsg) {
612 mcs_proto::DataMessageStanza data_message;
613 data_message.set_from(kDataMsgFrom);
614 data_message.set_category(kDataMsgCategory);
615 std::string handshake_request = EncodeHandshakeRequest();
616 std::string data_message_pkt =
617 EncodePacket(kDataMessageStanzaTag, data_message.SerializeAsString());
618 WriteList write_list;
619 write_list.push_back(net::MockWrite(net::ASYNC,
620 handshake_request.c_str(),
621 handshake_request.size()));
622 write_list.push_back(net::MockWrite(net::ASYNC,
623 data_message_pkt.c_str(),
624 data_message_pkt.size()));
625 std::string handshake_response = EncodeHandshakeResponse();
626 ReadList read_list;
627 read_list.push_back(net::MockRead(net::ASYNC,
628 handshake_response.c_str(),
629 handshake_response.size()));
630 read_list.push_back(net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING));
631 BuildSocket(read_list, write_list);
633 ScopedMessage received_message;
634 Connect(&received_message);
635 WaitForMessage(); // The login send.
636 WaitForMessage(); // The login response.
637 EXPECT_TRUE(connection_handler()->CanSendMessage());
638 connection_handler()->SendMessage(data_message);
639 EXPECT_FALSE(connection_handler()->CanSendMessage());
640 WaitForMessage(); // The message send.
641 EXPECT_TRUE(connection_handler()->CanSendMessage());
644 // Attempt to send a message after the socket is disconnected due to a timeout.
645 TEST_F(GCMConnectionHandlerImplTest, SendMsgSocketDisconnected) {
646 std::string handshake_request = EncodeHandshakeRequest();
647 WriteList write_list;
648 write_list.push_back(net::MockWrite(net::ASYNC,
649 handshake_request.c_str(),
650 handshake_request.size()));
651 std::string handshake_response = EncodeHandshakeResponse();
652 ReadList read_list;
653 read_list.push_back(net::MockRead(net::ASYNC,
654 handshake_response.c_str(),
655 handshake_response.size()));
656 read_list.push_back(net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING));
657 net::StreamSocket* socket = BuildSocket(read_list, write_list);
659 ScopedMessage received_message;
660 Connect(&received_message);
661 WaitForMessage(); // The login send.
662 WaitForMessage(); // The login response.
663 EXPECT_TRUE(connection_handler()->CanSendMessage());
664 socket->Disconnect();
665 mcs_proto::DataMessageStanza data_message;
666 data_message.set_from(kDataMsgFrom);
667 data_message.set_category(kDataMsgCategory);
668 connection_handler()->SendMessage(data_message);
669 EXPECT_FALSE(connection_handler()->CanSendMessage());
670 WaitForMessage(); // The message send. Should result in an error
671 EXPECT_FALSE(connection_handler()->CanSendMessage());
672 EXPECT_EQ(net::ERR_CONNECTION_CLOSED, last_error());
675 // Receive a message whose size field was corrupted and is larger than the
676 // socket's buffer. Should fail gracefully with a size error.
677 TEST_F(GCMConnectionHandlerImplTest, OutOfBuffer) {
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 // Fill a string with 9000 character zero.
685 std::string data_message_proto(9000, '0');
686 std::string data_message_pkt =
687 EncodePacket(kDataMessageStanzaTag, data_message_proto);
688 ReadList read_list;
689 read_list.push_back(net::MockRead(net::ASYNC,
690 handshake_response.c_str(),
691 handshake_response.size()));
692 read_list.push_back(net::MockRead(net::ASYNC,
693 data_message_pkt.c_str(),
694 data_message_pkt.size()));
695 BuildSocket(read_list, write_list);
697 ScopedMessage received_message;
698 Connect(&received_message);
699 WaitForMessage(); // The login send.
700 WaitForMessage(); // The login response.
701 received_message.reset();
702 WaitForMessage(); // The data message.
703 EXPECT_FALSE(received_message.get());
704 EXPECT_EQ(net::ERR_FILE_TOO_BIG, last_error());
707 // Receive a message whose size field was corrupted and takes more than two
708 // bytes to encode. Should fail gracefully with a size error.
709 TEST_F(GCMConnectionHandlerImplTest, InvalidSizePacket) {
710 std::string handshake_request = EncodeHandshakeRequest();
711 WriteList write_list(1, net::MockWrite(net::ASYNC,
712 handshake_request.c_str(),
713 handshake_request.size()));
714 std::string handshake_response = EncodeHandshakeResponse();
716 // Fill a string with 20000 character zero (which uses more than 2 bytes to
717 // encode the size packet).
718 std::string data_message_proto(20000, '0');
719 std::string data_message_pkt =
720 EncodePacket(kDataMessageStanzaTag, data_message_proto);
721 ReadList read_list;
722 read_list.push_back(net::MockRead(net::ASYNC,
723 handshake_response.c_str(),
724 handshake_response.size()));
725 read_list.push_back(net::MockRead(net::ASYNC,
726 data_message_pkt.c_str(),
727 data_message_pkt.size()));
728 BuildSocket(read_list, write_list);
730 ScopedMessage received_message;
731 Connect(&received_message);
732 WaitForMessage(); // The login send.
733 WaitForMessage(); // The login response.
734 received_message.reset();
735 WaitForMessage(); // The data message.
736 EXPECT_FALSE(received_message.get());
737 EXPECT_EQ(net::ERR_FILE_TOO_BIG, last_error());
740 // Make sure a message with an invalid tag is handled gracefully and resets
741 // the connection with an invalid argument error.
742 TEST_F(GCMConnectionHandlerImplTest, InvalidTag) {
743 std::string handshake_request = EncodeHandshakeRequest();
744 WriteList write_list(1, net::MockWrite(net::ASYNC,
745 handshake_request.c_str(),
746 handshake_request.size()));
747 std::string handshake_response = EncodeHandshakeResponse();
749 std::string invalid_message = "0";
750 std::string invalid_message_pkt =
751 EncodePacket(kInvalidTag, invalid_message);
752 ReadList read_list;
753 read_list.push_back(net::MockRead(net::ASYNC,
754 handshake_response.c_str(),
755 handshake_response.size()));
756 read_list.push_back(net::MockRead(net::ASYNC,
757 invalid_message_pkt.c_str(),
758 invalid_message_pkt.size()));
759 BuildSocket(read_list, write_list);
761 ScopedMessage received_message;
762 Connect(&received_message);
763 WaitForMessage(); // The login send.
764 WaitForMessage(); // The login response.
765 received_message.reset();
766 WaitForMessage(); // The invalid message.
767 EXPECT_FALSE(received_message.get());
768 EXPECT_EQ(net::ERR_INVALID_ARGUMENT, last_error());
771 // Receive a message where the size field spans two socket reads.
772 TEST_F(GCMConnectionHandlerImplTest, RecvMsgSplitSize) {
773 std::string handshake_request = EncodeHandshakeRequest();
774 WriteList write_list(1, net::MockWrite(net::ASYNC,
775 handshake_request.c_str(),
776 handshake_request.size()));
777 std::string handshake_response = EncodeHandshakeResponse();
779 std::string data_message_proto =
780 BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
781 std::string data_message_pkt =
782 EncodePacket(kDataMessageStanzaTag, data_message_proto);
783 DCHECK_GT(data_message_pkt.size(), 128U);
784 ReadList read_list;
785 read_list.push_back(net::MockRead(net::ASYNC,
786 handshake_response.c_str(),
787 handshake_response.size()));
788 // The first two bytes are the tag byte and the first byte of the size packet.
789 read_list.push_back(net::MockRead(net::ASYNC,
790 data_message_pkt.c_str(),
791 2));
792 // Start from the second byte of the size packet.
793 read_list.push_back(net::MockRead(net::ASYNC,
794 data_message_pkt.c_str() + 2,
795 data_message_pkt.size() - 2));
796 BuildSocket(read_list, write_list);
798 ScopedMessage received_message;
799 Connect(&received_message);
800 WaitForMessage(); // The login send.
801 WaitForMessage(); // The login response.
802 WaitForMessage(); // The data message.
803 ASSERT_TRUE(received_message.get());
804 EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
805 EXPECT_EQ(net::OK, last_error());
808 } // namespace
809 } // namespace gcm