6b89644462c05ea7a1b49ba913fce5d20e229297
[platform/framework/web/crosswalk.git] / src / google_apis / gcm / engine / connection_handler_impl_unittest.cc
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
45 // ---- Helpers for building messages. ----
46
47 // Encode a protobuf packet with protobuf type |tag| and serialized protobuf
48 // bytes |proto| into the MCS message form (tag + varint size + bytes).
49 std::string EncodePacket(uint8 tag, const std::string& proto) {
50   std::string result;
51   google::protobuf::io::StringOutputStream string_output_stream(&result);
52   {
53     google::protobuf::io::CodedOutputStream coded_output_stream(
54       &string_output_stream);
55     const unsigned char tag_byte[1] = { tag };
56     coded_output_stream.WriteRaw(tag_byte, 1);
57     coded_output_stream.WriteVarint32(proto.size());
58     coded_output_stream.WriteRaw(proto.c_str(), proto.size());
59     // ~CodedOutputStream must run before the move constructor at the
60     // return statement. http://crbug.com/338962
61   }
62   return result;
63 }
64
65 // Encode a handshake request into the MCS message form.
66 std::string EncodeHandshakeRequest() {
67   std::string result;
68   const char version_byte[1] = {kMCSVersion};
69   result.append(version_byte, 1);
70   ScopedMessage login_request(
71       BuildLoginRequest(kAuthId, kAuthToken, ""));
72   result.append(EncodePacket(kLoginRequestTag,
73                              login_request->SerializeAsString()));
74   return result;
75 }
76
77 // Build a serialized login response protobuf.
78 std::string BuildLoginResponse() {
79   std::string result;
80   mcs_proto::LoginResponse login_response;
81   login_response.set_id("id");
82   result.append(login_response.SerializeAsString());
83   return result;
84 }
85
86 // Encoode a handshake response into the MCS message form.
87 std::string EncodeHandshakeResponse() {
88   std::string result;
89   const char version_byte[1] = {kMCSVersion};
90   result.append(version_byte, 1);
91   result.append(EncodePacket(kLoginResponseTag, BuildLoginResponse()));
92   return result;
93 }
94
95 // Build a serialized data message stanza protobuf.
96 std::string BuildDataMessage(const std::string& from,
97                              const std::string& category) {
98   std::string result;
99   mcs_proto::DataMessageStanza data_message;
100   data_message.set_from(from);
101   data_message.set_category(category);
102   return data_message.SerializeAsString();
103 }
104
105 class GCMConnectionHandlerImplTest : public testing::Test {
106  public:
107   GCMConnectionHandlerImplTest();
108   virtual ~GCMConnectionHandlerImplTest();
109
110   net::StreamSocket* BuildSocket(const ReadList& read_list,
111                                  const WriteList& write_list);
112
113   // Pump |message_loop_|, resetting |run_loop_| after completion.
114   void PumpLoop();
115
116   ConnectionHandlerImpl* connection_handler() {
117     return connection_handler_.get();
118   }
119   base::MessageLoop* message_loop() { return &message_loop_; };
120   net::DelayedSocketData* data_provider() { return data_provider_.get(); }
121   int last_error() const { return last_error_; }
122
123   // Initialize the connection handler, setting |dst_proto| as the destination
124   // for any received messages.
125   void Connect(ScopedMessage* dst_proto);
126
127   // Runs the message loop until a message is received.
128   void WaitForMessage();
129
130  private:
131   void ReadContinuation(ScopedMessage* dst_proto, ScopedMessage new_proto);
132   void WriteContinuation();
133   void ConnectionContinuation(int error);
134
135   // SocketStreams and their data provider.
136   ReadList mock_reads_;
137   WriteList mock_writes_;
138   scoped_ptr<net::DelayedSocketData> data_provider_;
139   scoped_ptr<SocketInputStream> socket_input_stream_;
140   scoped_ptr<SocketOutputStream> socket_output_stream_;
141
142   // The connection handler being tested.
143   scoped_ptr<ConnectionHandlerImpl> connection_handler_;
144
145   // The last connection error received.
146   int last_error_;
147
148   // net:: components.
149   scoped_ptr<net::StreamSocket> socket_;
150   net::MockClientSocketFactory socket_factory_;
151   net::AddressList address_list_;
152
153   base::MessageLoopForIO message_loop_;
154   scoped_ptr<base::RunLoop> run_loop_;
155 };
156
157 GCMConnectionHandlerImplTest::GCMConnectionHandlerImplTest()
158   : last_error_(0) {
159   net::IPAddressNumber ip_number;
160   net::ParseIPLiteralToNumber("127.0.0.1", &ip_number);
161   address_list_ = net::AddressList::CreateFromIPAddress(ip_number, kMCSPort);
162 }
163
164 GCMConnectionHandlerImplTest::~GCMConnectionHandlerImplTest() {
165 }
166
167 net::StreamSocket* GCMConnectionHandlerImplTest::BuildSocket(
168     const ReadList& read_list,
169     const WriteList& write_list) {
170   mock_reads_ = read_list;
171   mock_writes_ = write_list;
172   data_provider_.reset(
173       new net::DelayedSocketData(0,
174                                  &(mock_reads_[0]), mock_reads_.size(),
175                                  &(mock_writes_[0]), mock_writes_.size()));
176   socket_factory_.AddSocketDataProvider(data_provider_.get());
177
178   socket_ = socket_factory_.CreateTransportClientSocket(
179       address_list_, NULL, net::NetLog::Source());
180   socket_->Connect(net::CompletionCallback());
181
182   run_loop_.reset(new base::RunLoop());
183   PumpLoop();
184
185   DCHECK(socket_->IsConnected());
186   return socket_.get();
187 }
188
189 void GCMConnectionHandlerImplTest::PumpLoop() {
190   run_loop_->RunUntilIdle();
191   run_loop_.reset(new base::RunLoop());
192 }
193
194 void GCMConnectionHandlerImplTest::Connect(
195     ScopedMessage* dst_proto) {
196   connection_handler_.reset(new ConnectionHandlerImpl(
197       TestTimeouts::tiny_timeout(),
198           base::Bind(&GCMConnectionHandlerImplTest::ReadContinuation,
199                      base::Unretained(this),
200                      dst_proto),
201           base::Bind(&GCMConnectionHandlerImplTest::WriteContinuation,
202                      base::Unretained(this)),
203           base::Bind(&GCMConnectionHandlerImplTest::ConnectionContinuation,
204                      base::Unretained(this))));
205   EXPECT_FALSE(connection_handler()->CanSendMessage());
206   connection_handler_->Init(
207       *BuildLoginRequest(kAuthId, kAuthToken, ""),
208       socket_.get());
209 }
210
211 void GCMConnectionHandlerImplTest::ReadContinuation(
212     ScopedMessage* dst_proto,
213     ScopedMessage new_proto) {
214   *dst_proto = new_proto.Pass();
215   run_loop_->Quit();
216 }
217
218 void GCMConnectionHandlerImplTest::WaitForMessage() {
219   run_loop_->Run();
220   run_loop_.reset(new base::RunLoop());
221 }
222
223 void GCMConnectionHandlerImplTest::WriteContinuation() {
224   run_loop_->Quit();
225 }
226
227 void GCMConnectionHandlerImplTest::ConnectionContinuation(int error) {
228   last_error_ = error;
229   run_loop_->Quit();
230 }
231
232 // Initialize the connection handler and ensure the handshake completes
233 // successfully.
234 TEST_F(GCMConnectionHandlerImplTest, Init) {
235   std::string handshake_request = EncodeHandshakeRequest();
236   WriteList write_list(1, net::MockWrite(net::ASYNC,
237                                          handshake_request.c_str(),
238                                          handshake_request.size()));
239   std::string handshake_response = EncodeHandshakeResponse();
240   ReadList read_list(1, net::MockRead(net::ASYNC,
241                                       handshake_response.c_str(),
242                                       handshake_response.size()));
243   BuildSocket(read_list, write_list);
244
245   ScopedMessage received_message;
246   Connect(&received_message);
247   EXPECT_FALSE(connection_handler()->CanSendMessage());
248   WaitForMessage();  // The login send.
249   WaitForMessage();  // The login response.
250   ASSERT_TRUE(received_message.get());
251   EXPECT_EQ(BuildLoginResponse(), received_message->SerializeAsString());
252   EXPECT_TRUE(connection_handler()->CanSendMessage());
253 }
254
255 // Simulate the handshake response returning an older version. Initialization
256 // should fail.
257 TEST_F(GCMConnectionHandlerImplTest, InitFailedVersionCheck) {
258   std::string handshake_request = EncodeHandshakeRequest();
259   WriteList write_list(1, net::MockWrite(net::ASYNC,
260                                          handshake_request.c_str(),
261                                          handshake_request.size()));
262   std::string handshake_response = EncodeHandshakeResponse();
263   // Overwrite the version byte.
264   handshake_response[0] = 37;
265   ReadList read_list(1, net::MockRead(net::ASYNC,
266                                       handshake_response.c_str(),
267                                       handshake_response.size()));
268   BuildSocket(read_list, write_list);
269
270   ScopedMessage received_message;
271   Connect(&received_message);
272   WaitForMessage();  // The login send.
273   WaitForMessage();  // The login response. Should result in a connection error.
274   EXPECT_FALSE(received_message.get());
275   EXPECT_FALSE(connection_handler()->CanSendMessage());
276   EXPECT_EQ(net::ERR_FAILED, last_error());
277 }
278
279 // Attempt to initialize, but receive no server response, resulting in a time
280 // out.
281 TEST_F(GCMConnectionHandlerImplTest, InitTimeout) {
282   std::string handshake_request = EncodeHandshakeRequest();
283   WriteList write_list(1, net::MockWrite(net::ASYNC,
284                                          handshake_request.c_str(),
285                                          handshake_request.size()));
286   ReadList read_list(1, net::MockRead(net::SYNCHRONOUS,
287                                       net::ERR_IO_PENDING));
288   BuildSocket(read_list, write_list);
289
290   ScopedMessage received_message;
291   Connect(&received_message);
292   WaitForMessage();  // The login send.
293   WaitForMessage();  // The login response. Should result in a connection error.
294   EXPECT_FALSE(received_message.get());
295   EXPECT_FALSE(connection_handler()->CanSendMessage());
296   EXPECT_EQ(net::ERR_TIMED_OUT, last_error());
297 }
298
299 // Attempt to initialize, but receive an incomplete server response, resulting
300 // in a time out.
301 TEST_F(GCMConnectionHandlerImplTest, InitIncompleteTimeout) {
302   std::string handshake_request = EncodeHandshakeRequest();
303   WriteList write_list(1, net::MockWrite(net::ASYNC,
304                                          handshake_request.c_str(),
305                                          handshake_request.size()));
306   std::string handshake_response = EncodeHandshakeResponse();
307   ReadList read_list;
308   read_list.push_back(net::MockRead(net::ASYNC,
309                                     handshake_response.c_str(),
310                                     handshake_response.size() / 2));
311   read_list.push_back(net::MockRead(net::SYNCHRONOUS,
312                                     net::ERR_IO_PENDING));
313   BuildSocket(read_list, write_list);
314
315   ScopedMessage received_message;
316   Connect(&received_message);
317   WaitForMessage();  // The login send.
318   WaitForMessage();  // The login response. Should result in a connection error.
319   EXPECT_FALSE(received_message.get());
320   EXPECT_FALSE(connection_handler()->CanSendMessage());
321   EXPECT_EQ(net::ERR_TIMED_OUT, last_error());
322 }
323
324 // Reinitialize the connection handler after failing to initialize.
325 TEST_F(GCMConnectionHandlerImplTest, ReInit) {
326   std::string handshake_request = EncodeHandshakeRequest();
327   WriteList write_list(1, net::MockWrite(net::ASYNC,
328                                          handshake_request.c_str(),
329                                          handshake_request.size()));
330   ReadList read_list(1, net::MockRead(net::SYNCHRONOUS,
331                                       net::ERR_IO_PENDING));
332   BuildSocket(read_list, write_list);
333
334   ScopedMessage received_message;
335   Connect(&received_message);
336   WaitForMessage();  // The login send.
337   WaitForMessage();  // The login response. Should result in a connection error.
338   EXPECT_FALSE(received_message.get());
339   EXPECT_FALSE(connection_handler()->CanSendMessage());
340   EXPECT_EQ(net::ERR_TIMED_OUT, last_error());
341
342   // Build a new socket and reconnect, successfully this time.
343   std::string handshake_response = EncodeHandshakeResponse();
344   read_list[0] = net::MockRead(net::ASYNC,
345                                handshake_response.c_str(),
346                                handshake_response.size());
347   BuildSocket(read_list, write_list);
348   Connect(&received_message);
349   EXPECT_FALSE(connection_handler()->CanSendMessage());
350   WaitForMessage();  // The login send.
351   WaitForMessage();  // The login response.
352   ASSERT_TRUE(received_message.get());
353   EXPECT_EQ(BuildLoginResponse(), received_message->SerializeAsString());
354   EXPECT_TRUE(connection_handler()->CanSendMessage());
355 }
356
357 // Verify that messages can be received after initialization.
358 TEST_F(GCMConnectionHandlerImplTest, RecvMsg) {
359   std::string handshake_request = EncodeHandshakeRequest();
360   WriteList write_list(1, net::MockWrite(net::ASYNC,
361                                          handshake_request.c_str(),
362                                          handshake_request.size()));
363   std::string handshake_response = EncodeHandshakeResponse();
364
365   std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
366                                                     kDataMsgCategory);
367   std::string data_message_pkt =
368       EncodePacket(kDataMessageStanzaTag, data_message_proto);
369   ReadList read_list;
370   read_list.push_back(net::MockRead(net::ASYNC,
371                                     handshake_response.c_str(),
372                                     handshake_response.size()));
373   read_list.push_back(net::MockRead(net::ASYNC,
374                                     data_message_pkt.c_str(),
375                                     data_message_pkt.size()));
376   BuildSocket(read_list, write_list);
377
378   ScopedMessage received_message;
379   Connect(&received_message);
380   WaitForMessage();  // The login send.
381   WaitForMessage();  // The login response.
382   WaitForMessage();  // The data message.
383   ASSERT_TRUE(received_message.get());
384   EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
385   EXPECT_EQ(net::OK, last_error());
386 }
387
388 // Verify that if two messages arrive at once, they're treated appropriately.
389 TEST_F(GCMConnectionHandlerImplTest, Recv2Msgs) {
390   std::string handshake_request = EncodeHandshakeRequest();
391   WriteList write_list(1, net::MockWrite(net::ASYNC,
392                                          handshake_request.c_str(),
393                                          handshake_request.size()));
394   std::string handshake_response = EncodeHandshakeResponse();
395
396   std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
397                                                     kDataMsgCategory);
398   std::string data_message_proto2 = BuildDataMessage(kDataMsgFrom2,
399                                                      kDataMsgCategory2);
400   std::string data_message_pkt =
401       EncodePacket(kDataMessageStanzaTag, data_message_proto);
402   data_message_pkt += EncodePacket(kDataMessageStanzaTag, data_message_proto2);
403   ReadList read_list;
404   read_list.push_back(net::MockRead(net::ASYNC,
405                                     handshake_response.c_str(),
406                                     handshake_response.size()));
407   read_list.push_back(net::MockRead(net::SYNCHRONOUS,
408                                     data_message_pkt.c_str(),
409                                     data_message_pkt.size()));
410   BuildSocket(read_list, write_list);
411
412   ScopedMessage received_message;
413   Connect(&received_message);
414   WaitForMessage();  // The login send.
415   WaitForMessage();  // The login response.
416   WaitForMessage();  // The first data message.
417   ASSERT_TRUE(received_message.get());
418   EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
419   received_message.reset();
420   WaitForMessage();  // The second data message.
421   ASSERT_TRUE(received_message.get());
422   EXPECT_EQ(data_message_proto2, received_message->SerializeAsString());
423   EXPECT_EQ(net::OK, last_error());
424 }
425
426 // Receive a long (>128 bytes) message.
427 TEST_F(GCMConnectionHandlerImplTest, RecvLongMsg) {
428   std::string handshake_request = EncodeHandshakeRequest();
429   WriteList write_list(1, net::MockWrite(net::ASYNC,
430                                          handshake_request.c_str(),
431                                          handshake_request.size()));
432   std::string handshake_response = EncodeHandshakeResponse();
433
434   std::string data_message_proto =
435       BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
436   std::string data_message_pkt =
437       EncodePacket(kDataMessageStanzaTag, data_message_proto);
438   DCHECK_GT(data_message_pkt.size(), 128U);
439   ReadList read_list;
440   read_list.push_back(net::MockRead(net::ASYNC,
441                                     handshake_response.c_str(),
442                                     handshake_response.size()));
443   read_list.push_back(net::MockRead(net::ASYNC,
444                                     data_message_pkt.c_str(),
445                                     data_message_pkt.size()));
446   BuildSocket(read_list, write_list);
447
448   ScopedMessage received_message;
449   Connect(&received_message);
450   WaitForMessage();  // The login send.
451   WaitForMessage();  // The login response.
452   WaitForMessage();  // The data message.
453   ASSERT_TRUE(received_message.get());
454   EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
455   EXPECT_EQ(net::OK, last_error());
456 }
457
458 // Receive a long (>128 bytes) message in two synchronous parts.
459 TEST_F(GCMConnectionHandlerImplTest, RecvLongMsg2Parts) {
460   std::string handshake_request = EncodeHandshakeRequest();
461   WriteList write_list(1, net::MockWrite(net::ASYNC,
462                                          handshake_request.c_str(),
463                                          handshake_request.size()));
464   std::string handshake_response = EncodeHandshakeResponse();
465
466   std::string data_message_proto =
467       BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
468   std::string data_message_pkt =
469       EncodePacket(kDataMessageStanzaTag, data_message_proto);
470   DCHECK_GT(data_message_pkt.size(), 128U);
471   ReadList read_list;
472   read_list.push_back(net::MockRead(net::ASYNC,
473                                     handshake_response.c_str(),
474                                     handshake_response.size()));
475
476   int bytes_in_first_message = data_message_pkt.size() / 2;
477   read_list.push_back(net::MockRead(net::SYNCHRONOUS,
478                                     data_message_pkt.c_str(),
479                                     bytes_in_first_message));
480   read_list.push_back(net::MockRead(net::SYNCHRONOUS,
481                                     data_message_pkt.c_str() +
482                                         bytes_in_first_message,
483                                     data_message_pkt.size() -
484                                         bytes_in_first_message));
485   BuildSocket(read_list, write_list);
486
487   ScopedMessage received_message;
488   Connect(&received_message);
489   WaitForMessage();  // The login send.
490   WaitForMessage();  // The login response.
491   WaitForMessage();  // The data message.
492   ASSERT_TRUE(received_message.get());
493   EXPECT_EQ(net::OK, last_error());
494   EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
495 }
496
497 // Receive two long (>128 bytes) message.
498 TEST_F(GCMConnectionHandlerImplTest, Recv2LongMsgs) {
499   std::string handshake_request = EncodeHandshakeRequest();
500   WriteList write_list(1, net::MockWrite(net::ASYNC,
501                                          handshake_request.c_str(),
502                                          handshake_request.size()));
503   std::string handshake_response = EncodeHandshakeResponse();
504
505   std::string data_message_proto =
506       BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
507   std::string data_message_proto2 =
508       BuildDataMessage(kDataMsgFromLong2, kDataMsgCategoryLong2);
509   std::string data_message_pkt =
510       EncodePacket(kDataMessageStanzaTag, data_message_proto);
511   data_message_pkt += EncodePacket(kDataMessageStanzaTag, data_message_proto2);
512   DCHECK_GT(data_message_pkt.size(), 256U);
513   ReadList read_list;
514   read_list.push_back(net::MockRead(net::ASYNC,
515                                     handshake_response.c_str(),
516                                     handshake_response.size()));
517   read_list.push_back(net::MockRead(net::SYNCHRONOUS,
518                                     data_message_pkt.c_str(),
519                                     data_message_pkt.size()));
520   BuildSocket(read_list, write_list);
521
522   ScopedMessage received_message;
523   Connect(&received_message);
524   WaitForMessage();  // The login send.
525   WaitForMessage();  // The login response.
526   WaitForMessage();  // The first data message.
527   ASSERT_TRUE(received_message.get());
528   EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
529   received_message.reset();
530   WaitForMessage();  // The second data message.
531   ASSERT_TRUE(received_message.get());
532   EXPECT_EQ(data_message_proto2, received_message->SerializeAsString());
533   EXPECT_EQ(net::OK, last_error());
534 }
535
536 // Simulate a message where the end of the data does not arrive in time and the
537 // read times out.
538 TEST_F(GCMConnectionHandlerImplTest, ReadTimeout) {
539   std::string handshake_request = EncodeHandshakeRequest();
540   WriteList write_list(1, net::MockWrite(net::ASYNC,
541                                          handshake_request.c_str(),
542                                          handshake_request.size()));
543   std::string handshake_response = EncodeHandshakeResponse();
544
545   std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
546                                                     kDataMsgCategory);
547   std::string data_message_pkt =
548       EncodePacket(kDataMessageStanzaTag, data_message_proto);
549   int bytes_in_first_message = data_message_pkt.size() / 2;
550   ReadList read_list;
551   read_list.push_back(net::MockRead(net::ASYNC,
552                                     handshake_response.c_str(),
553                                     handshake_response.size()));
554   read_list.push_back(net::MockRead(net::ASYNC,
555                                     data_message_pkt.c_str(),
556                                     bytes_in_first_message));
557   read_list.push_back(net::MockRead(net::SYNCHRONOUS,
558                                     net::ERR_IO_PENDING));
559   read_list.push_back(net::MockRead(net::ASYNC,
560                                     data_message_pkt.c_str() +
561                                         bytes_in_first_message,
562                                     data_message_pkt.size() -
563                                         bytes_in_first_message));
564   BuildSocket(read_list, write_list);
565
566   ScopedMessage received_message;
567   Connect(&received_message);
568   WaitForMessage();  // The login send.
569   WaitForMessage();  // The login response.
570   received_message.reset();
571   WaitForMessage();  // Should time out.
572   EXPECT_FALSE(received_message.get());
573   EXPECT_EQ(net::ERR_TIMED_OUT, last_error());
574   EXPECT_FALSE(connection_handler()->CanSendMessage());
575
576   // Finish the socket read. Should have no effect.
577   data_provider()->ForceNextRead();
578 }
579
580 // Receive a message with zero data bytes.
581 TEST_F(GCMConnectionHandlerImplTest, RecvMsgNoData) {
582   std::string handshake_request = EncodeHandshakeRequest();
583   WriteList write_list(1, net::MockWrite(net::ASYNC,
584                                          handshake_request.c_str(),
585                                          handshake_request.size()));
586   std::string handshake_response = EncodeHandshakeResponse();
587
588   std::string data_message_pkt = EncodePacket(kHeartbeatPingTag, "");
589   ASSERT_EQ(data_message_pkt.size(), 2U);
590   ReadList read_list;
591   read_list.push_back(net::MockRead(net::ASYNC,
592                                     handshake_response.c_str(),
593                                     handshake_response.size()));
594   read_list.push_back(net::MockRead(net::ASYNC,
595                                     data_message_pkt.c_str(),
596                                     data_message_pkt.size()));
597   BuildSocket(read_list, write_list);
598
599   ScopedMessage received_message;
600   Connect(&received_message);
601   WaitForMessage();  // The login send.
602   WaitForMessage();  // The login response.
603   received_message.reset();
604   WaitForMessage();  // The heartbeat ping.
605   EXPECT_TRUE(received_message.get());
606   EXPECT_EQ(GetMCSProtoTag(*received_message), kHeartbeatPingTag);
607   EXPECT_EQ(net::OK, last_error());
608   EXPECT_TRUE(connection_handler()->CanSendMessage());
609 }
610
611 // Send a message after performing the handshake.
612 TEST_F(GCMConnectionHandlerImplTest, SendMsg) {
613   mcs_proto::DataMessageStanza data_message;
614   data_message.set_from(kDataMsgFrom);
615   data_message.set_category(kDataMsgCategory);
616   std::string handshake_request = EncodeHandshakeRequest();
617   std::string data_message_pkt =
618       EncodePacket(kDataMessageStanzaTag, data_message.SerializeAsString());
619   WriteList write_list;
620   write_list.push_back(net::MockWrite(net::ASYNC,
621                                       handshake_request.c_str(),
622                                       handshake_request.size()));
623   write_list.push_back(net::MockWrite(net::ASYNC,
624                                       data_message_pkt.c_str(),
625                                       data_message_pkt.size()));
626   std::string handshake_response = EncodeHandshakeResponse();
627   ReadList read_list;
628   read_list.push_back(net::MockRead(net::ASYNC,
629                                     handshake_response.c_str(),
630                                     handshake_response.size()));
631   read_list.push_back(net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING));
632   BuildSocket(read_list, write_list);
633
634   ScopedMessage received_message;
635   Connect(&received_message);
636   WaitForMessage();  // The login send.
637   WaitForMessage();  // The login response.
638   EXPECT_TRUE(connection_handler()->CanSendMessage());
639   connection_handler()->SendMessage(data_message);
640   EXPECT_FALSE(connection_handler()->CanSendMessage());
641   WaitForMessage();  // The message send.
642   EXPECT_TRUE(connection_handler()->CanSendMessage());
643 }
644
645 // Attempt to send a message after the socket is disconnected due to a timeout.
646 TEST_F(GCMConnectionHandlerImplTest, SendMsgSocketDisconnected) {
647   std::string handshake_request = EncodeHandshakeRequest();
648   WriteList write_list;
649   write_list.push_back(net::MockWrite(net::ASYNC,
650                                       handshake_request.c_str(),
651                                       handshake_request.size()));
652   std::string handshake_response = EncodeHandshakeResponse();
653   ReadList read_list;
654   read_list.push_back(net::MockRead(net::ASYNC,
655                                     handshake_response.c_str(),
656                                     handshake_response.size()));
657   read_list.push_back(net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING));
658   net::StreamSocket* socket = BuildSocket(read_list, write_list);
659
660   ScopedMessage received_message;
661   Connect(&received_message);
662   WaitForMessage();  // The login send.
663   WaitForMessage();  // The login response.
664   EXPECT_TRUE(connection_handler()->CanSendMessage());
665   socket->Disconnect();
666   mcs_proto::DataMessageStanza data_message;
667   data_message.set_from(kDataMsgFrom);
668   data_message.set_category(kDataMsgCategory);
669   connection_handler()->SendMessage(data_message);
670   EXPECT_FALSE(connection_handler()->CanSendMessage());
671   WaitForMessage();  // The message send. Should result in an error
672   EXPECT_FALSE(connection_handler()->CanSendMessage());
673   EXPECT_EQ(net::ERR_CONNECTION_CLOSED, last_error());
674 }
675
676 // Receive a message whose size field was corrupted and is larger than the
677 // socket's buffer. Should fail gracefully.
678 TEST_F(GCMConnectionHandlerImplTest, CorruptedSize) {
679   std::string handshake_request = EncodeHandshakeRequest();
680   WriteList write_list(1, net::MockWrite(net::ASYNC,
681                                          handshake_request.c_str(),
682                                          handshake_request.size()));
683   std::string handshake_response = EncodeHandshakeResponse();
684
685   // Fill a string with 9000 character zero.
686   std::string data_message_proto(9000, '0');
687   std::string data_message_pkt =
688       EncodePacket(kDataMessageStanzaTag, data_message_proto);
689   ReadList read_list;
690   read_list.push_back(net::MockRead(net::ASYNC,
691                                     handshake_response.c_str(),
692                                     handshake_response.size()));
693   read_list.push_back(net::MockRead(net::ASYNC,
694                                     data_message_pkt.c_str(),
695                                     data_message_pkt.size()));
696   BuildSocket(read_list, write_list);
697
698   ScopedMessage received_message;
699   Connect(&received_message);
700   WaitForMessage();  // The login send.
701   WaitForMessage();  // The login response.
702   received_message.reset();
703   WaitForMessage();  // The data message.
704   EXPECT_FALSE(received_message.get());
705   EXPECT_EQ(net::ERR_FILE_TOO_BIG, last_error());
706 }
707
708 }  // namespace
709 }  // namespace gcm