OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "google_apis/gcm/engine/connection_handler_impl.h" | 5 #include "google_apis/gcm/engine/connection_handler_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 23 matching lines...) Expand all Loading... |
34 const char kDataMsgFrom2[] = "data_from2"; | 34 const char kDataMsgFrom2[] = "data_from2"; |
35 const char kDataMsgCategory2[] = "data_category2"; | 35 const char kDataMsgCategory2[] = "data_category2"; |
36 const char kDataMsgFromLong[] = | 36 const char kDataMsgFromLong[] = |
37 "this is a long from that will result in a message > 128 bytes"; | 37 "this is a long from that will result in a message > 128 bytes"; |
38 const char kDataMsgCategoryLong[] = | 38 const char kDataMsgCategoryLong[] = |
39 "this is a long category that will result in a message > 128 bytes"; | 39 "this is a long category that will result in a message > 128 bytes"; |
40 const char kDataMsgFromLong2[] = | 40 const char kDataMsgFromLong2[] = |
41 "this is a second long from that will result in a message > 128 bytes"; | 41 "this is a second long from that will result in a message > 128 bytes"; |
42 const char kDataMsgCategoryLong2[] = | 42 const char kDataMsgCategoryLong2[] = |
43 "this is a second long category that will result in a message > 128 bytes"; | 43 "this is a second long category that will result in a message > 128 bytes"; |
| 44 const uint8 kInvalidTag = 100; // An invalid tag. |
44 | 45 |
45 // ---- Helpers for building messages. ---- | 46 // ---- Helpers for building messages. ---- |
46 | 47 |
47 // Encode a protobuf packet with protobuf type |tag| and serialized protobuf | 48 // Encode a protobuf packet with protobuf type |tag| and serialized protobuf |
48 // bytes |proto| into the MCS message form (tag + varint size + bytes). | 49 // bytes |proto| into the MCS message form (tag + varint size + bytes). |
49 std::string EncodePacket(uint8 tag, const std::string& proto) { | 50 std::string EncodePacket(uint8 tag, const std::string& proto) { |
50 std::string result; | 51 std::string result; |
51 google::protobuf::io::StringOutputStream string_output_stream(&result); | 52 google::protobuf::io::StringOutputStream string_output_stream(&result); |
52 { | 53 { |
53 google::protobuf::io::CodedOutputStream coded_output_stream( | 54 google::protobuf::io::CodedOutputStream coded_output_stream( |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 | 130 |
130 private: | 131 private: |
131 void ReadContinuation(ScopedMessage* dst_proto, ScopedMessage new_proto); | 132 void ReadContinuation(ScopedMessage* dst_proto, ScopedMessage new_proto); |
132 void WriteContinuation(); | 133 void WriteContinuation(); |
133 void ConnectionContinuation(int error); | 134 void ConnectionContinuation(int error); |
134 | 135 |
135 // SocketStreams and their data provider. | 136 // SocketStreams and their data provider. |
136 ReadList mock_reads_; | 137 ReadList mock_reads_; |
137 WriteList mock_writes_; | 138 WriteList mock_writes_; |
138 scoped_ptr<net::DelayedSocketData> data_provider_; | 139 scoped_ptr<net::DelayedSocketData> data_provider_; |
139 scoped_ptr<SocketInputStream> socket_input_stream_; | |
140 scoped_ptr<SocketOutputStream> socket_output_stream_; | |
141 | 140 |
142 // The connection handler being tested. | 141 // The connection handler being tested. |
143 scoped_ptr<ConnectionHandlerImpl> connection_handler_; | 142 scoped_ptr<ConnectionHandlerImpl> connection_handler_; |
144 | 143 |
145 // The last connection error received. | 144 // The last connection error received. |
146 int last_error_; | 145 int last_error_; |
147 | 146 |
148 // net:: components. | 147 // net:: components. |
149 scoped_ptr<net::StreamSocket> socket_; | 148 scoped_ptr<net::StreamSocket> socket_; |
150 net::MockClientSocketFactory socket_factory_; | 149 net::MockClientSocketFactory socket_factory_; |
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 data_message.set_from(kDataMsgFrom); | 666 data_message.set_from(kDataMsgFrom); |
668 data_message.set_category(kDataMsgCategory); | 667 data_message.set_category(kDataMsgCategory); |
669 connection_handler()->SendMessage(data_message); | 668 connection_handler()->SendMessage(data_message); |
670 EXPECT_FALSE(connection_handler()->CanSendMessage()); | 669 EXPECT_FALSE(connection_handler()->CanSendMessage()); |
671 WaitForMessage(); // The message send. Should result in an error | 670 WaitForMessage(); // The message send. Should result in an error |
672 EXPECT_FALSE(connection_handler()->CanSendMessage()); | 671 EXPECT_FALSE(connection_handler()->CanSendMessage()); |
673 EXPECT_EQ(net::ERR_CONNECTION_CLOSED, last_error()); | 672 EXPECT_EQ(net::ERR_CONNECTION_CLOSED, last_error()); |
674 } | 673 } |
675 | 674 |
676 // Receive a message whose size field was corrupted and is larger than the | 675 // Receive a message whose size field was corrupted and is larger than the |
677 // socket's buffer. Should fail gracefully. | 676 // socket's buffer. Should fail gracefully with a size error. |
678 TEST_F(GCMConnectionHandlerImplTest, CorruptedSize) { | 677 TEST_F(GCMConnectionHandlerImplTest, OutOfBuffer) { |
679 std::string handshake_request = EncodeHandshakeRequest(); | 678 std::string handshake_request = EncodeHandshakeRequest(); |
680 WriteList write_list(1, net::MockWrite(net::ASYNC, | 679 WriteList write_list(1, net::MockWrite(net::ASYNC, |
681 handshake_request.c_str(), | 680 handshake_request.c_str(), |
682 handshake_request.size())); | 681 handshake_request.size())); |
683 std::string handshake_response = EncodeHandshakeResponse(); | 682 std::string handshake_response = EncodeHandshakeResponse(); |
684 | 683 |
685 // Fill a string with 9000 character zero. | 684 // Fill a string with 9000 character zero. |
686 std::string data_message_proto(9000, '0'); | 685 std::string data_message_proto(9000, '0'); |
687 std::string data_message_pkt = | 686 std::string data_message_pkt = |
688 EncodePacket(kDataMessageStanzaTag, data_message_proto); | 687 EncodePacket(kDataMessageStanzaTag, data_message_proto); |
689 ReadList read_list; | 688 ReadList read_list; |
690 read_list.push_back(net::MockRead(net::ASYNC, | 689 read_list.push_back(net::MockRead(net::ASYNC, |
691 handshake_response.c_str(), | 690 handshake_response.c_str(), |
692 handshake_response.size())); | 691 handshake_response.size())); |
693 read_list.push_back(net::MockRead(net::ASYNC, | 692 read_list.push_back(net::MockRead(net::ASYNC, |
694 data_message_pkt.c_str(), | 693 data_message_pkt.c_str(), |
695 data_message_pkt.size())); | 694 data_message_pkt.size())); |
696 BuildSocket(read_list, write_list); | 695 BuildSocket(read_list, write_list); |
697 | 696 |
698 ScopedMessage received_message; | 697 ScopedMessage received_message; |
699 Connect(&received_message); | 698 Connect(&received_message); |
700 WaitForMessage(); // The login send. | 699 WaitForMessage(); // The login send. |
701 WaitForMessage(); // The login response. | 700 WaitForMessage(); // The login response. |
702 received_message.reset(); | 701 received_message.reset(); |
703 WaitForMessage(); // The data message. | 702 WaitForMessage(); // The data message. |
704 EXPECT_FALSE(received_message.get()); | 703 EXPECT_FALSE(received_message.get()); |
705 EXPECT_EQ(net::ERR_FILE_TOO_BIG, last_error()); | 704 EXPECT_EQ(net::ERR_FILE_TOO_BIG, last_error()); |
706 } | 705 } |
707 | 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 |
708 } // namespace | 808 } // namespace |
709 } // namespace gcm | 809 } // namespace gcm |
OLD | NEW |