Upstream version 5.34.104.0
[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 }
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 }
423
424 // Receive a long (>128 bytes) message.
425 TEST_F(GCMConnectionHandlerImplTest, RecvLongMsg) {
426   std::string handshake_request = EncodeHandshakeRequest();
427   WriteList write_list(1, net::MockWrite(net::ASYNC,
428                                          handshake_request.c_str(),
429                                          handshake_request.size()));
430   std::string handshake_response = EncodeHandshakeResponse();
431
432   std::string data_message_proto =
433       BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
434   std::string data_message_pkt =
435       EncodePacket(kDataMessageStanzaTag, data_message_proto);
436   DCHECK_GT(data_message_pkt.size(), 128U);
437   ReadList read_list;
438   read_list.push_back(net::MockRead(net::ASYNC,
439                                     handshake_response.c_str(),
440                                     handshake_response.size()));
441   read_list.push_back(net::MockRead(net::ASYNC,
442                                     data_message_pkt.c_str(),
443                                     data_message_pkt.size()));
444   BuildSocket(read_list, write_list);
445
446   ScopedMessage received_message;
447   Connect(&received_message);
448   WaitForMessage();  // The login send.
449   WaitForMessage();  // The login response.
450   WaitForMessage();  // The data message.
451   ASSERT_TRUE(received_message.get());
452   EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
453 }
454
455 // Receive two long (>128 bytes) message.
456 TEST_F(GCMConnectionHandlerImplTest, Recv2LongMsgs) {
457   std::string handshake_request = EncodeHandshakeRequest();
458   WriteList write_list(1, net::MockWrite(net::ASYNC,
459                                          handshake_request.c_str(),
460                                          handshake_request.size()));
461   std::string handshake_response = EncodeHandshakeResponse();
462
463   std::string data_message_proto =
464       BuildDataMessage(kDataMsgFromLong, kDataMsgCategoryLong);
465   std::string data_message_proto2 =
466       BuildDataMessage(kDataMsgFromLong2, kDataMsgCategoryLong2);
467   std::string data_message_pkt =
468       EncodePacket(kDataMessageStanzaTag, data_message_proto);
469   data_message_pkt += EncodePacket(kDataMessageStanzaTag, data_message_proto2);
470   DCHECK_GT(data_message_pkt.size(), 256U);
471   ReadList read_list;
472   read_list.push_back(net::MockRead(net::ASYNC,
473                                     handshake_response.c_str(),
474                                     handshake_response.size()));
475   read_list.push_back(net::MockRead(net::SYNCHRONOUS,
476                                     data_message_pkt.c_str(),
477                                     data_message_pkt.size()));
478   BuildSocket(read_list, write_list);
479
480   ScopedMessage received_message;
481   Connect(&received_message);
482   WaitForMessage();  // The login send.
483   WaitForMessage();  // The login response.
484   WaitForMessage();  // The first data message.
485   ASSERT_TRUE(received_message.get());
486   EXPECT_EQ(data_message_proto, received_message->SerializeAsString());
487   received_message.reset();
488   WaitForMessage();  // The second data message.
489   ASSERT_TRUE(received_message.get());
490   EXPECT_EQ(data_message_proto2, received_message->SerializeAsString());
491 }
492
493 // Simulate a message where the end of the data does not arrive in time and the
494 // read times out.
495 TEST_F(GCMConnectionHandlerImplTest, ReadTimeout) {
496   std::string handshake_request = EncodeHandshakeRequest();
497   WriteList write_list(1, net::MockWrite(net::ASYNC,
498                                          handshake_request.c_str(),
499                                          handshake_request.size()));
500   std::string handshake_response = EncodeHandshakeResponse();
501
502   std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
503                                                     kDataMsgCategory);
504   std::string data_message_pkt =
505       EncodePacket(kDataMessageStanzaTag, data_message_proto);
506   int bytes_in_first_message = data_message_pkt.size() / 2;
507   ReadList read_list;
508   read_list.push_back(net::MockRead(net::ASYNC,
509                                     handshake_response.c_str(),
510                                     handshake_response.size()));
511   read_list.push_back(net::MockRead(net::ASYNC,
512                                     data_message_pkt.c_str(),
513                                     bytes_in_first_message));
514   read_list.push_back(net::MockRead(net::SYNCHRONOUS,
515                                     net::ERR_IO_PENDING));
516   read_list.push_back(net::MockRead(net::ASYNC,
517                                     data_message_pkt.c_str() +
518                                         bytes_in_first_message,
519                                     data_message_pkt.size() -
520                                         bytes_in_first_message));
521   BuildSocket(read_list, write_list);
522
523   ScopedMessage received_message;
524   Connect(&received_message);
525   WaitForMessage();  // The login send.
526   WaitForMessage();  // The login response.
527   received_message.reset();
528   WaitForMessage();  // Should time out.
529   EXPECT_FALSE(received_message.get());
530   EXPECT_EQ(net::ERR_TIMED_OUT, last_error());
531   EXPECT_FALSE(connection_handler()->CanSendMessage());
532
533   // Finish the socket read. Should have no effect.
534   data_provider()->ForceNextRead();
535 }
536
537 // Receive a message with zero data bytes.
538 TEST_F(GCMConnectionHandlerImplTest, RecvMsgNoData) {
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_pkt = EncodePacket(kHeartbeatPingTag, "");
546   ASSERT_EQ(data_message_pkt.size(), 2U);
547   ReadList read_list;
548   read_list.push_back(net::MockRead(net::ASYNC,
549                                     handshake_response.c_str(),
550                                     handshake_response.size()));
551   read_list.push_back(net::MockRead(net::ASYNC,
552                                     data_message_pkt.c_str(),
553                                     data_message_pkt.size()));
554   BuildSocket(read_list, write_list);
555
556   ScopedMessage received_message;
557   Connect(&received_message);
558   WaitForMessage();  // The login send.
559   WaitForMessage();  // The login response.
560   received_message.reset();
561   WaitForMessage();  // The heartbeat ping.
562   EXPECT_TRUE(received_message.get());
563   EXPECT_EQ(GetMCSProtoTag(*received_message), kHeartbeatPingTag);
564   EXPECT_EQ(net::OK, last_error());
565   EXPECT_TRUE(connection_handler()->CanSendMessage());
566 }
567
568 // Send a message after performing the handshake.
569 TEST_F(GCMConnectionHandlerImplTest, SendMsg) {
570   mcs_proto::DataMessageStanza data_message;
571   data_message.set_from(kDataMsgFrom);
572   data_message.set_category(kDataMsgCategory);
573   std::string handshake_request = EncodeHandshakeRequest();
574   std::string data_message_pkt =
575       EncodePacket(kDataMessageStanzaTag, data_message.SerializeAsString());
576   WriteList write_list;
577   write_list.push_back(net::MockWrite(net::ASYNC,
578                                       handshake_request.c_str(),
579                                       handshake_request.size()));
580   write_list.push_back(net::MockWrite(net::ASYNC,
581                                       data_message_pkt.c_str(),
582                                       data_message_pkt.size()));
583   std::string handshake_response = EncodeHandshakeResponse();
584   ReadList read_list;
585   read_list.push_back(net::MockRead(net::ASYNC,
586                                     handshake_response.c_str(),
587                                     handshake_response.size()));
588   read_list.push_back(net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING));
589   BuildSocket(read_list, write_list);
590
591   ScopedMessage received_message;
592   Connect(&received_message);
593   WaitForMessage();  // The login send.
594   WaitForMessage();  // The login response.
595   EXPECT_TRUE(connection_handler()->CanSendMessage());
596   connection_handler()->SendMessage(data_message);
597   EXPECT_FALSE(connection_handler()->CanSendMessage());
598   WaitForMessage();  // The message send.
599   EXPECT_TRUE(connection_handler()->CanSendMessage());
600 }
601
602 // Attempt to send a message after the socket is disconnected due to a timeout.
603 TEST_F(GCMConnectionHandlerImplTest, SendMsgSocketDisconnected) {
604   std::string handshake_request = EncodeHandshakeRequest();
605   WriteList write_list;
606   write_list.push_back(net::MockWrite(net::ASYNC,
607                                       handshake_request.c_str(),
608                                       handshake_request.size()));
609   std::string handshake_response = EncodeHandshakeResponse();
610   ReadList read_list;
611   read_list.push_back(net::MockRead(net::ASYNC,
612                                     handshake_response.c_str(),
613                                     handshake_response.size()));
614   read_list.push_back(net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING));
615   net::StreamSocket* socket = BuildSocket(read_list, write_list);
616
617   ScopedMessage received_message;
618   Connect(&received_message);
619   WaitForMessage();  // The login send.
620   WaitForMessage();  // The login response.
621   EXPECT_TRUE(connection_handler()->CanSendMessage());
622   socket->Disconnect();
623   mcs_proto::DataMessageStanza data_message;
624   data_message.set_from(kDataMsgFrom);
625   data_message.set_category(kDataMsgCategory);
626   connection_handler()->SendMessage(data_message);
627   EXPECT_FALSE(connection_handler()->CanSendMessage());
628   WaitForMessage();  // The message send. Should result in an error
629   EXPECT_FALSE(connection_handler()->CanSendMessage());
630   EXPECT_EQ(net::ERR_CONNECTION_CLOSED, last_error());
631 }
632
633 }  // namespace
634 }  // namespace gcm