Upstream version 11.40.277.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 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