Home | History | Annotate | Download | only in engine
      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