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.
5 #include "google_apis/gcm/engine/connection_handler_impl.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"
24 typedef scoped_ptr<google::protobuf::MessageLite> ScopedMessage;
25 typedef std::vector<net::MockRead> ReadList;
26 typedef std::vector<net::MockWrite> WriteList;
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";
45 // ---- Helpers for building messages. ----
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) {
51 google::protobuf::io::StringOutputStream string_output_stream(&result);
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
65 // Encode a handshake request into the MCS message form.
66 std::string EncodeHandshakeRequest() {
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()));
77 // Build a serialized login response protobuf.
78 std::string BuildLoginResponse() {
80 mcs_proto::LoginResponse login_response;
81 login_response.set_id("id");
82 result.append(login_response.SerializeAsString());
86 // Encoode a handshake response into the MCS message form.
87 std::string EncodeHandshakeResponse() {
89 const char version_byte[1] = {kMCSVersion};
90 result.append(version_byte, 1);
91 result.append(EncodePacket(kLoginResponseTag, BuildLoginResponse()));
95 // Build a serialized data message stanza protobuf.
96 std::string BuildDataMessage(const std::string& from,
97 const std::string& category) {
99 mcs_proto::DataMessageStanza data_message;
100 data_message.set_from(from);
101 data_message.set_category(category);
102 return data_message.SerializeAsString();
105 class GCMConnectionHandlerImplTest : public testing::Test {
107 GCMConnectionHandlerImplTest();
108 virtual ~GCMConnectionHandlerImplTest();
110 net::StreamSocket* BuildSocket(const ReadList& read_list,
111 const WriteList& write_list);
113 // Pump |message_loop_|, resetting |run_loop_| after completion.
116 ConnectionHandlerImpl* connection_handler() {
117 return connection_handler_.get();
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_; }
123 // Initialize the connection handler, setting |dst_proto| as the destination
124 // for any received messages.
125 void Connect(ScopedMessage* dst_proto);
127 // Runs the message loop until a message is received.
128 void WaitForMessage();
131 void ReadContinuation(ScopedMessage* dst_proto, ScopedMessage new_proto);
132 void WriteContinuation();
133 void ConnectionContinuation(int error);
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_;
142 // The connection handler being tested.
143 scoped_ptr<ConnectionHandlerImpl> connection_handler_;
145 // The last connection error received.
149 scoped_ptr<net::StreamSocket> socket_;
150 net::MockClientSocketFactory socket_factory_;
151 net::AddressList address_list_;
153 base::MessageLoopForIO message_loop_;
154 scoped_ptr<base::RunLoop> run_loop_;
157 GCMConnectionHandlerImplTest::GCMConnectionHandlerImplTest()
159 net::IPAddressNumber ip_number;
160 net::ParseIPLiteralToNumber("127.0.0.1", &ip_number);
161 address_list_ = net::AddressList::CreateFromIPAddress(ip_number, kMCSPort);
164 GCMConnectionHandlerImplTest::~GCMConnectionHandlerImplTest() {
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());
178 socket_ = socket_factory_.CreateTransportClientSocket(
179 address_list_, NULL, net::NetLog::Source());
180 socket_->Connect(net::CompletionCallback());
182 run_loop_.reset(new base::RunLoop());
185 DCHECK(socket_->IsConnected());
186 return socket_.get();
189 void GCMConnectionHandlerImplTest::PumpLoop() {
190 run_loop_->RunUntilIdle();
191 run_loop_.reset(new base::RunLoop());
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),
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, ""),
211 void GCMConnectionHandlerImplTest::ReadContinuation(
212 ScopedMessage* dst_proto,
213 ScopedMessage new_proto) {
214 *dst_proto = new_proto.Pass();
218 void GCMConnectionHandlerImplTest::WaitForMessage() {
220 run_loop_.reset(new base::RunLoop());
223 void GCMConnectionHandlerImplTest::WriteContinuation() {
227 void GCMConnectionHandlerImplTest::ConnectionContinuation(int error) {
232 // Initialize the connection handler and ensure the handshake completes
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);
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());
255 // Simulate the handshake response returning an older version. Initialization
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);
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());
279 // Attempt to initialize, but receive no server response, resulting in a time
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);
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());
299 // Attempt to initialize, but receive an incomplete server response, resulting
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();
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);
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());
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);
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());
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());
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();
365 std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
367 std::string data_message_pkt =
368 EncodePacket(kDataMessageStanzaTag, data_message_proto);
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);
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());
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();
395 std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
397 std::string data_message_proto2 = BuildDataMessage(kDataMsgFrom2,
399 std::string data_message_pkt =
400 EncodePacket(kDataMessageStanzaTag, data_message_proto);
401 data_message_pkt += EncodePacket(kDataMessageStanzaTag, data_message_proto2);
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);
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());
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();
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);
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);
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());
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();
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);
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);
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());
493 // Simulate a message where the end of the data does not arrive in time and the
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();
502 std::string data_message_proto = BuildDataMessage(kDataMsgFrom,
504 std::string data_message_pkt =
505 EncodePacket(kDataMessageStanzaTag, data_message_proto);
506 int bytes_in_first_message = data_message_pkt.size() / 2;
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);
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());
533 // Finish the socket read. Should have no effect.
534 data_provider()->ForceNextRead();
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();
545 std::string data_message_pkt = EncodePacket(kHeartbeatPingTag, "");
546 ASSERT_EQ(data_message_pkt.size(), 2U);
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);
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());
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();
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);
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());
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();
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);
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());