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. 4 5 #include "google_apis/gcm/engine/connection_handler_impl.h" 6 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" 20 21 namespace gcm { 22 namespace { 23 24 typedef scoped_ptr<google::protobuf::MessageLite> ScopedMessage; 25 typedef std::vector<net::MockRead> ReadList; 26 typedef std::vector<net::MockWrite> WriteList; 27 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. 45 46 // ---- Helpers for building messages. ---- 47 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); 53 { 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 62 } 63 return result; 64 } 65 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; 76 } 77 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; 85 } 86 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; 94 } 95 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(); 104 } 105 106 class GCMConnectionHandlerImplTest : public testing::Test { 107 public: 108 GCMConnectionHandlerImplTest(); 109 virtual ~GCMConnectionHandlerImplTest(); 110 111 net::StreamSocket* BuildSocket(const ReadList& read_list, 112 const WriteList& write_list); 113 114 // Pump |message_loop_|, resetting |run_loop_| after completion. 115 void PumpLoop(); 116 117 ConnectionHandlerImpl* connection_handler() { 118 return connection_handler_.get(); 119 } 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_; } 123 124 // Initialize the connection handler, setting |dst_proto| as the destination 125 // for any received messages. 126 void Connect(ScopedMessage* dst_proto); 127 128 // Runs the message loop until a message is received. 129 void WaitForMessage(); 130 131 private: 132 void ReadContinuation(ScopedMessage* dst_proto, ScopedMessage new_proto); 133 void WriteContinuation(); 134 void ConnectionContinuation(int error); 135 136 // SocketStreams and their data provider. 137 ReadList mock_reads_; 138 WriteList mock_writes_; 139 scoped_ptr<net::DelayedSocketData> data_provider_; 140 141 // The connection handler being tested. 142 scoped_ptr<ConnectionHandlerImpl> connection_handler_; 143 144 // The last connection error received. 145 int last_error_; 146 147 // net:: components. 148 scoped_ptr<net::StreamSocket> socket_; 149 net::MockClientSocketFactory socket_factory_; 150 net::AddressList address_list_; 151 152 base::MessageLoopForIO message_loop_; 153 scoped_ptr<base::RunLoop> run_loop_; 154 }; 155 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); 161 } 162 163 GCMConnectionHandlerImplTest::~GCMConnectionHandlerImplTest() { 164 } 165 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()); 176 177 socket_ = socket_factory_.CreateTransportClientSocket( 178 address_list_, NULL, net::NetLog::Source()); 179 socket_->Connect(net::CompletionCallback()); 180 181 run_loop_.reset(new base::RunLoop()); 182 PumpLoop(); 183 184 DCHECK(socket_->IsConnected()); 185 return socket_.get(); 186 } 187 188 void GCMConnectionHandlerImplTest::PumpLoop() { 189 run_loop_->RunUntilIdle(); 190 run_loop_.reset(new base::RunLoop()); 191 } 192 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()); 208 } 209 210 void GCMConnectionHandlerImplTest::ReadContinuation( 211 ScopedMessage* dst_proto, 212 ScopedMessage new_proto) { 213 *dst_proto = new_proto.Pass(); 214 run_loop_->Quit(); 215 } 216 217 void GCMConnectionHandlerImplTest::WaitForMessage() { 218 run_loop_->Run(); 219 run_loop_.reset(new base::RunLoop()); 220 } 221 222 void GCMConnectionHandlerImplTest::WriteContinuation() { 223 run_loop_->Quit(); 224 } 225 226 void GCMConnectionHandlerImplTest::ConnectionContinuation(int error) { 227 last_error_ = error; 228 run_loop_->Quit(); 229 } 230 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); 243 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()); 252 } 253 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); 268 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()); 276 } 277 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); 288 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()); 296 } 297 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); 313 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()); 321 } 322 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); 332 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()); 340 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()); 354 } 355 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(); 363 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); 376 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()); 385 } 386 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(); 394 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); 410 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()); 423 } 424 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(); 432 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); 446 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()); 455 } 456 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(); 464 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())); 474 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); 485 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()); 494 } 495 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(); 503 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); 520 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()); 533 } 534 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(); 543 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); 564 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()); 574 575 // Finish the socket read. Should have no effect. 576 data_provider()->ForceNextRead(); 577 } 578 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(); 586 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); 597 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()); 608 } 609 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); 632 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()); 642 } 643 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); 658 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()); 673 } 674 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(); 683 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); 696 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()); 705 } 706 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(); 715 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); 729 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()); 738 } 739 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(); 748 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); 760 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()); 769 } 770 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(); 778 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); 797 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()); 806 } 807 808 } // namespace 809 } // namespace gcm 810