1ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// Copyright 2013 The Chromium Authors. All rights reserved. 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Use of this source code is governed by a BSD-style license that can be 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com// found in the LICENSE file. 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "google_apis/gcm/engine/connection_handler_impl.h" 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "base/bind.h" 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "base/memory/scoped_ptr.h" 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com#include "base/run_loop.h" 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "base/strings/string_number_conversions.h" 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "base/test/test_timeouts.h" 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "google/protobuf/io/coded_stream.h" 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "google/protobuf/io/zero_copy_stream_impl_lite.h" 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "google_apis/gcm/base/mcs_util.h" 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "google_apis/gcm/base/socket_stream.h" 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "google_apis/gcm/protocol/mcs.pb.h" 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "net/socket/socket_test_util.h" 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "net/socket/stream_socket.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "testing/gtest/include/gtest/gtest.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comnamespace gcm { 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comnamespace { 23d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com 24d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comtypedef scoped_ptr<google::protobuf::MessageLite> ScopedMessage; 25d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comtypedef std::vector<net::MockRead> ReadList; 26d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comtypedef std::vector<net::MockWrite> WriteList; 27a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com 28d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comconst uint64 kAuthId = 54321; 29d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comconst uint64 kAuthToken = 12345; 30a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.comconst char kMCSVersion = 41; // The protocol version. 31a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.comconst int kMCSPort = 5228; // The server port. 32a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.comconst char kDataMsgFrom[] = "data_from"; 33a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.comconst char kDataMsgCategory[] = "data_category"; 34d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comconst char kDataMsgFrom2[] = "data_from2"; 35d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comconst char kDataMsgCategory2[] = "data_category2"; 36d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comconst char kDataMsgFromLong[] = 37d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com "this is a long from that will result in a message > 128 bytes"; 38a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.comconst char kDataMsgCategoryLong[] = 39a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com "this is a long category that will result in a message > 128 bytes"; 40a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.comconst char kDataMsgFromLong2[] = 41d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com "this is a second long from that will result in a message > 128 bytes"; 42a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.comconst char kDataMsgCategoryLong2[] = 43d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com "this is a second long category that will result in a message > 128 bytes"; 44d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comconst uint8 kInvalidTag = 100; // An invalid tag. 45a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com 46a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com// ---- Helpers for building messages. ---- 47d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com 48d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com// Encode a protobuf packet with protobuf type |tag| and serialized protobuf 49d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com// bytes |proto| into the MCS message form (tag + varint size + bytes). 50d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comstd::string EncodePacket(uint8 tag, const std::string& proto) { 51d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com std::string result; 52ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com google::protobuf::io::StringOutputStream string_output_stream(&result); 53ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com { 54ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com google::protobuf::io::CodedOutputStream coded_output_stream( 55ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com &string_output_stream); 56ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com const unsigned char tag_byte[1] = { tag }; 57ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com coded_output_stream.WriteRaw(tag_byte, 1); 58ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com coded_output_stream.WriteVarint32(proto.size()); 59ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com coded_output_stream.WriteRaw(proto.c_str(), proto.size()); 60ba28d03e94dc221d6a803bf2a84a420b9159255cdjsollen@google.com // ~CodedOutputStream must run before the move constructor at the 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // return statement. http://crbug.com/338962 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return result; 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Encode a handshake request into the MCS message form. 677ffb1b21abcc7bbed5a0fc711f6dd7b9dbb4f577ctguil@chromium.orgstd::string EncodeHandshakeRequest() { 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com std::string result; 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char version_byte[1] = {kMCSVersion}; 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result.append(version_byte, 1); 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ScopedMessage login_request( 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BuildLoginRequest(kAuthId, kAuthToken, "")); 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result.append(EncodePacket(kLoginRequestTag, 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com login_request->SerializeAsString())); 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return result; 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Build a serialized login response protobuf. 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstd::string BuildLoginResponse() { 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com std::string result; 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mcs_proto::LoginResponse login_response; 82a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com login_response.set_id("id"); 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result.append(login_response.SerializeAsString()); 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return result; 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// Encoode a handshake response into the MCS message form. 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstd::string EncodeHandshakeResponse() { 89a2ca41e3afdd8fad5e0e924dec029f33918e0a67djsollen@google.com std::string result; 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const char version_byte[1] = {kMCSVersion}; 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com result.append(version_byte, 1); 9254924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com result.append(EncodePacket(kLoginResponseTag, BuildLoginResponse())); 9354924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com return result; 9454924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com} 9554924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com 9654924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com// Build a serialized data message stanza protobuf. 97d26147adbbdca85f07dff432025afee0c8614387caryclark@google.comstd::string BuildDataMessage(const std::string& from, 98d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com const std::string& category) { 99d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com std::string result; 100d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com mcs_proto::DataMessageStanza data_message; 101d26147adbbdca85f07dff432025afee0c8614387caryclark@google.com data_message.set_from(from); 1029d0c6ecb8440e8e546881a4ff850eb6333f24541caryclark@google.com data_message.set_category(category); 1039d0c6ecb8440e8e546881a4ff850eb6333f24541caryclark@google.com return data_message.SerializeAsString(); 10454924243c1b65b3ee6d8fa064b50a9b1bb2a19a5djsollen@google.com} 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comclass GCMConnectionHandlerImplTest : public testing::Test { 107f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com public: 108f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com GCMConnectionHandlerImplTest(); 109f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com virtual ~GCMConnectionHandlerImplTest(); 110f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com 111f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com net::StreamSocket* BuildSocket(const ReadList& read_list, 112f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com const WriteList& write_list); 113f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com 114f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com // Pump |message_loop_|, resetting |run_loop_| after completion. 115f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com void PumpLoop(); 116f2eb5ab7806a62e89b8cb572b1b33b70b83b13abreed@google.com 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ConnectionHandlerImpl* connection_handler() { 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return connection_handler_.get(); 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::MessageLoop* message_loop() { return &message_loop_; }; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com net::DelayedSocketData* data_provider() { return data_provider_.get(); } 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int last_error() const { return last_error_; } 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Initialize the connection handler, setting |dst_proto| as the destination 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // for any received messages. 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void Connect(ScopedMessage* dst_proto); 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // Runs the message loop until a message is received. 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void WaitForMessage(); 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com private: 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void ReadContinuation(ScopedMessage* dst_proto, ScopedMessage new_proto); 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void WriteContinuation(); 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com void ConnectionContinuation(int error); 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // SocketStreams and their data provider. 1376bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com ReadList mock_reads_; 1386bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com WriteList mock_writes_; 1396bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com scoped_ptr<net::DelayedSocketData> data_provider_; 1406bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 1416bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com // The connection handler being tested. 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scoped_ptr<ConnectionHandlerImpl> connection_handler_; 1436bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // The last connection error received. 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int last_error_; 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1476bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com // net:: components. 1486bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com scoped_ptr<net::StreamSocket> socket_; 1496bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com net::MockClientSocketFactory socket_factory_; 1506bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com net::AddressList address_list_; 1516bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 1526bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com base::MessageLoopForIO message_loop_; 1536bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com scoped_ptr<base::RunLoop> run_loop_; 1546bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com}; 1556bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 1566bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.comGCMConnectionHandlerImplTest::GCMConnectionHandlerImplTest() 1576bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com : last_error_(0) { 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com net::IPAddressNumber ip_number; 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com net::ParseIPLiteralToNumber("127.0.0.1", &ip_number); 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com address_list_ = net::AddressList::CreateFromIPAddress(ip_number, kMCSPort); 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comGCMConnectionHandlerImplTest::~GCMConnectionHandlerImplTest() { 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comnet::StreamSocket* GCMConnectionHandlerImplTest::BuildSocket( 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const ReadList& read_list, 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const WriteList& write_list) { 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mock_reads_ = read_list; 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mock_writes_ = write_list; 1716bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com data_provider_.reset( 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com new net::DelayedSocketData(0, 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com &(mock_reads_[0]), mock_reads_.size(), 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com &(mock_writes_[0]), mock_writes_.size())); 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com socket_factory_.AddSocketDataProvider(data_provider_.get()); 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com socket_ = socket_factory_.CreateTransportClientSocket( 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com address_list_, NULL, net::NetLog::Source()); 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com socket_->Connect(net::CompletionCallback()); 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com run_loop_.reset(new base::RunLoop()); 182e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org PumpLoop(); 183e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org 184e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org DCHECK(socket_->IsConnected()); 185e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org return socket_.get(); 186e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org} 187e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid GCMConnectionHandlerImplTest::PumpLoop() { 189e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org run_loop_->RunUntilIdle(); 190e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org run_loop_.reset(new base::RunLoop()); 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid GCMConnectionHandlerImplTest::Connect( 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ScopedMessage* dst_proto) { 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com connection_handler_.reset(new ConnectionHandlerImpl( 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com TestTimeouts::tiny_timeout(), 197e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org base::Bind(&GCMConnectionHandlerImplTest::ReadContinuation, 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Unretained(this), 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst_proto), 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Bind(&GCMConnectionHandlerImplTest::WriteContinuation, 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Unretained(this)), 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Bind(&GCMConnectionHandlerImplTest::ConnectionContinuation, 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com base::Unretained(this)))); 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_FALSE(connection_handler()->CanSendMessage()); 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com connection_handler_->Init( 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *BuildLoginRequest(kAuthId, kAuthToken, ""), 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com socket_.get()); 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 209e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org 210e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.orgvoid GCMConnectionHandlerImplTest::ReadContinuation( 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ScopedMessage* dst_proto, 212e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org ScopedMessage new_proto) { 213e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org *dst_proto = new_proto.Pass(); 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com run_loop_->Quit(); 215e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org} 216e9e08cc7b29f97ee9e823e68c3daf0f55c84b21amike@reedtribe.org 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid GCMConnectionHandlerImplTest::WaitForMessage() { 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com run_loop_->Run(); 2196bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com run_loop_.reset(new base::RunLoop()); 2206bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com} 2216bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 2226bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.comvoid GCMConnectionHandlerImplTest::WriteContinuation() { 2236bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com run_loop_->Quit(); 2246bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com} 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2266bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.comvoid GCMConnectionHandlerImplTest::ConnectionContinuation(int error) { 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com last_error_ = error; 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com run_loop_->Quit(); 2296bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com} 2306bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 2316bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com// Initialize the connection handler and ensure the handshake completes 2326bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com// successfully. 2336bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.comTEST_F(GCMConnectionHandlerImplTest, Init) { 2346bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com std::string handshake_request = EncodeHandshakeRequest(); 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com WriteList write_list(1, net::MockWrite(net::ASYNC, 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com handshake_request.c_str(), 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com handshake_request.size())); 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com std::string handshake_response = EncodeHandshakeResponse(); 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ReadList read_list(1, net::MockRead(net::ASYNC, 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com handshake_response.c_str(), 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com handshake_response.size())); 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com BuildSocket(read_list, write_list); 2436bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com 2446bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com ScopedMessage received_message; 2456bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com Connect(&received_message); 2466bac947cd5bc460dd9166ada6310d678fd2e39f8reed@google.com EXPECT_FALSE(connection_handler()->CanSendMessage()); 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com WaitForMessage(); // The login send. 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com WaitForMessage(); // The login response. 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ASSERT_TRUE(received_message.get()); 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_EQ(BuildLoginResponse(), received_message->SerializeAsString()); 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com EXPECT_TRUE(connection_handler()->CanSendMessage()); 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 253 254// Simulate the handshake response returning an older version. Initialization 255// should fail. 256TEST_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. 280TEST_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. 300TEST_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. 324TEST_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. 357TEST_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. 388TEST_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. 426TEST_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. 458TEST_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. 497TEST_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. 537TEST_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. 580TEST_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. 611TEST_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. 645TEST_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. 677TEST_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. 709TEST_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. 742TEST_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. 772TEST_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 810