15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/api/socket/tls_socket.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <deque> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <utility> 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/string_piece.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/address_list.h" 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/completion_callback.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/io_buffer.h" 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/net_errors.h" 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/base/rand_callback.h" 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/socket/ssl_client_socket.h" 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/socket/tcp_client_socket.h" 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h" 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::_; 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::DoAll; 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::Invoke; 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::Gt; 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::Return; 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::SaveArg; 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using testing::WithArgs; 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)using base::StringPiece; 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace extensions { 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class MockSSLClientSocket : public net::SSLClientSocket { 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockSSLClientSocket() {} 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD0(Disconnect, void()); 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD3(Read, 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(net::IOBuffer* buf, 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buf_len, 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback)); 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD3(Write, 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(net::IOBuffer* buf, 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buf_len, 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback)); 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(SetReceiveBufferSize, int(int32)); 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(SetSendBufferSize, int(int32)); 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(Connect, int(const CompletionCallback&)); 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(IsConnectedAndIdle, bool()); 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD1(GetPeerAddress, int(net::IPEndPoint*)); 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD1(GetLocalAddress, int(net::IPEndPoint*)); 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(NetLog, const net::BoundNetLog&()); 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD0(SetSubresourceSpeculation, void()); 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD0(SetOmniboxSpeculation, void()); 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(WasEverUsed, bool()); 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(UsingTCPFastOpen, bool()); 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(GetSSLInfo, bool(net::SSLInfo*)); 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD5(ExportKeyingMaterial, 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(const StringPiece&, 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool, 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const StringPiece&, 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned char*, 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unsigned int)); 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(GetTLSUniqueChannelBinding, int(std::string*)); 6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) MOCK_CONST_METHOD0(GetSessionCacheKey, std::string()); 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(InSessionCache, bool()); 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(SetHandshakeCompletionCallback, void(const base::Closure&)); 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(GetSSLCertRequestInfo, void(net::SSLCertRequestInfo*)); 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(GetNextProto, 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::SSLClientSocket::NextProtoStatus(std::string*)); 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(GetUnverifiedServerCertificateChain, 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::X509Certificate>()); 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_CONST_METHOD0(GetChannelIDService, net::ChannelIDService*()); 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual bool IsConnected() const OVERRIDE { return true; } 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockSSLClientSocket); 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class MockTCPSocket : public net::TCPClientSocket { 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) explicit MockTCPSocket(const net::AddressList& address_list) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : net::TCPClientSocket(address_list, NULL, net::NetLog::Source()) {} 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD3(Read, 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(net::IOBuffer* buf, 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buf_len, 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback)); 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD3(Write, 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int(net::IOBuffer* buf, 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int buf_len, 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const net::CompletionCallback& callback)); 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD2(SetKeepAlive, bool(bool enable, int delay)); 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(SetNoDelay, bool(bool no_delay)); 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual bool IsConnected() const OVERRIDE { return true; } 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MockTCPSocket); 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CompleteHandler { 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler() {} 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD1(OnComplete, void(int result_code)); 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD2(OnReadComplete, 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void(int result_code, scoped_refptr<net::IOBuffer> io_buffer)); 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MOCK_METHOD2(OnAccept, void(int, net::TCPClientSocket*)); 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) private: 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(CompleteHandler); 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TLSSocketTest : public ::testing::Test { 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TLSSocketTest() {} 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void SetUp() { 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::AddressList address_list; 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_| is owned by |socket_|. TLSSocketTest keeps a pointer to 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // it to expect invocations from TLSSocket to |ssl_socket_|. 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<MockSSLClientSocket> ssl_sock(new MockSSLClientSocket); 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ssl_socket_ = ssl_sock.get(); 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_.reset(new TLSSocket(ssl_sock.PassAs<net::StreamSocket>(), 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "test_extension_id")); 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Disconnect()).Times(1); 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) virtual void TearDown() { 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ssl_socket_ = NULL; 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_.reset(); 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }; 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) protected: 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MockSSLClientSocket* ssl_socket_; 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_ptr<TLSSocket> socket_; 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Verify that a Read() on TLSSocket will pass through into a Read() on 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// |ssl_socket_| and invoke its completion callback. 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketRead) { 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handler; 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Read(_, _, _)).Times(1); 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handler, OnReadComplete(_, _)).Times(1); 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int count = 512; 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Read( 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) count, 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnReadComplete, base::Unretained(&handler))); 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Verify that a Write() on a TLSSocket will pass through to Write() 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// invocations on |ssl_socket_|, handling partial writes correctly, and calls 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// the completion callback correctly. 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketWrite) { 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handler; 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::CompletionCallback callback; 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Write(_, _, _)).Times(2).WillRepeatedly( 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoAll(SaveArg<2>(&callback), Return(128))); 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handler, OnComplete(_)).Times(1); 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::IOBufferWithSize> io_buffer( 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) new net::IOBufferWithSize(256)); 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Write( 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffer.get(), 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffer->size(), 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Simulate a blocked Write, and verify that, when simulating the Write going 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// through, the callback gets invoked. 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketBlockedWrite) { 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handler; 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::CompletionCallback callback; 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Return ERR_IO_PENDING to say the Write()'s blocked. Save the |callback| 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Write()'s passed. 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Write(_, _, _)).Times(2).WillRepeatedly( 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING))); 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::IOBufferWithSize> io_buffer(new net::IOBufferWithSize(42)); 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Write( 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffer.get(), 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffer->size(), 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // After the simulated asynchronous writes come back (via calls to 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // callback.Run()), hander's OnComplete() should get invoked with the total 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // amount written. 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handler, OnComplete(42)).Times(1); 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(40); 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(2); 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Simulate multiple blocked Write()s. 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketBlockedWriteReentry) { 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kNumIOs = 5; 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handlers[kNumIOs]; 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::CompletionCallback callback; 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIOs]; 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The implementation of TLSSocket::Write() is inherited from 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Socket::Write(), which implements an internal write queue that wraps 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TLSSocket::WriteImpl(). Each call from TLSSocket::WriteImpl() will invoke 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_|'s Write() (mocked here). Save the |callback| (assume they 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // will all be equivalent), and return ERR_IO_PENDING, to indicate a blocked 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // request. The mocked SSLClientSocket::Write() will get one request per 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TLSSocket::Write() request invoked on |socket_| below. 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Write(_, _, _)).Times(kNumIOs).WillRepeatedly( 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoAll(SaveArg<2>(&callback), Return(net::ERR_IO_PENDING))); 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Send out |kNuMIOs| requests, each with a different size. 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (int i = 0; i < kNumIOs; i++) { 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i] = new net::IOBufferWithSize(128 + i * 50); 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Write(io_buffers[i].get(), 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i]->size(), 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnComplete, 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Unretained(&handlers[i]))); 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Set up expectations on all |kNumIOs| handlers. 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handlers[i], OnComplete(io_buffers[i]->size())).Times(1); 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Finish each pending I/O. This should satisfy the expectations on the 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // handlers. 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (int i = 0; i < kNumIOs; i++) { 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) callback.Run(128 + i * 50); 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)typedef std::pair<net::CompletionCallback, int> PendingCallback; 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class CallbackList : public std::deque<PendingCallback> { 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public: 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) void append(const net::CompletionCallback& cb, int arg) { 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) push_back(std::make_pair(cb, arg)); 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Simulate Write()s above and below a SSLClientSocket size limit. 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(TLSSocketTest, TestTLSSocketLargeWrites) { 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kSizeIncrement = 4096; 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kNumIncrements = 10; 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kFragmentIncrement = 4; 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const int kSizeLimit = kSizeIncrement * kFragmentIncrement; 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) net::CompletionCallback callback; 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CompleteHandler handler; 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) scoped_refptr<net::IOBufferWithSize> io_buffers[kNumIncrements]; 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) CallbackList pending_callbacks; 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t total_bytes_requested = 0; 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t total_bytes_written = 0; 2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Some implementations of SSLClientSocket may have write-size limits (e.g, 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // max 1 TLS record, which is 16k). This test mocks a size limit at 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |kSizeIncrement| and calls Write() above and below that limit. It 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // simulates SSLClientSocket::Write() behavior in only writing up to the size 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // limit, requiring additional calls for the remaining data to be sent. 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Socket::Write() (and supporting methods) execute the additional calls as 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // needed. This test verifies that this inherited implementation does 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // properly issue additional calls, and that the total amount returned from 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // all mocked SSLClientSocket::Write() calls is the same as originally 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // requested. 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_|'s Write() will write at most |kSizeLimit| bytes. The 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // inherited Socket::Write() will repeatedly call |ssl_socket_|'s Write() 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // until the entire original request is sent. Socket::Write() will queue any 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // additional write requests until the current request is complete. A 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // request is complete when the callback passed to Socket::WriteImpl() is 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // invoked with an argument equal to the original number of bytes requested 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // from Socket::Write(). If the callback is invoked with a smaller number, 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Socket::WriteImpl() will get repeatedly invoked until the sum of the 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // callbacks' arguments is equal to the original requested amount. 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(*ssl_socket_, Write(_, _, _)).WillRepeatedly( 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DoAll(WithArgs<2, 1>(Invoke(&pending_callbacks, &CallbackList::append)), 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Return(net::ERR_IO_PENDING))); 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Observe what comes back from Socket::Write() here. 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) EXPECT_CALL(handler, OnComplete(Gt(0))).Times(kNumIncrements); 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Send out |kNumIncrements| requests, each with a different size. The 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // last request is the same size as the first, and the ones in the middle 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // are monotonically increasing from the first. 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (int i = 0; i < kNumIncrements; i++) { 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const bool last = i == (kNumIncrements - 1); 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i] = new net::IOBufferWithSize(last ? kSizeIncrement 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : kSizeIncrement * (i + 1)); 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) total_bytes_requested += io_buffers[i]->size(); 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Invoke Socket::Write(). This will invoke |ssl_socket_|'s Write(), which 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // this test mocks out. That mocked Write() is in an asynchronous waiting 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // state until the passed callback (saved in the EXPECT_CALL for 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_|'s Write()) is invoked. 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) socket_->Write( 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i].get(), 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) io_buffers[i]->size(), 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base::Bind(&CompleteHandler::OnComplete, base::Unretained(&handler))); 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Invoke callbacks for pending I/Os. These can synchronously invoke more of 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // |ssl_socket_|'s Write() as needed. The callback checks how much is left 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // in the request, and then starts issuing any queued Socket::Write() 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // invocations. 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while (!pending_callbacks.empty()) { 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PendingCallback cb = pending_callbacks.front(); 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pending_callbacks.pop_front(); 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int amount_written_invocation = std::min(kSizeLimit, cb.second); 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) total_bytes_written += amount_written_invocation; 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) cb.first.Run(amount_written_invocation); 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ASSERT_EQ(total_bytes_requested, total_bytes_written) 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "There should be exactly as many bytes written as originally " 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << "requested to Write()."; 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace extensions 318