Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(649)

Unified Diff: net/spdy/spdy_proxy_client_socket_unittest.cc

Issue 3432009: Add a new class SpdyProxyClientSocket which implements ClientSocket... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 10 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/spdy/spdy_proxy_client_socket.cc ('k') | net/spdy/spdy_session.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/spdy/spdy_proxy_client_socket_unittest.cc
===================================================================
--- net/spdy/spdy_proxy_client_socket_unittest.cc (revision 0)
+++ net/spdy/spdy_proxy_client_socket_unittest.cc (revision 0)
@@ -0,0 +1,894 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/spdy/spdy_proxy_client_socket.h"
+
+#include "base/utf_string_conversions.h"
+#include "net/base/address_list.h"
+#include "net/base/net_log.h"
+#include "net/base/net_log_unittest.h"
+#include "net/base/mock_host_resolver.h"
+#include "net/base/test_completion_callback.h"
+#include "net/base/winsock_init.h"
+#include "net/http/http_response_info.h"
+#include "net/http/http_response_headers.h"
+#include "net/socket/client_socket_factory.h"
+#include "net/socket/tcp_client_socket.h"
+#include "net/socket/socket_test_util.h"
+#include "net/spdy/spdy_protocol.h"
+#include "net/spdy/spdy_session_pool.h"
+#include "net/spdy/spdy_test_util.h"
+#include "testing/platform_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+//-----------------------------------------------------------------------------
+
+namespace {
+
+static const char kUrl[] = "https://www.google.com/";
+static const char kOriginHost[] = "www.google.com";
+static const int kOriginPort = 443;
+static const char kOriginHostPort[] = "www.google.com:443";
+static const char kProxyUrl[] = "http://myproxy:6121/";
+static const char kProxyHost[] = "myproxy";
+static const int kProxyPort = 6121;
+static const char kUserAgent[] = "Mozilla/1.0";
+
+static const int kStreamId = 1;
+
+static const char kMsg1[] = "\0hello!\xff";
+static const int kLen1 = 8;
+static const char kMsg2[] = "\012345678\0";
+static const int kLen2 = 10;
+static const char kMsg3[] = "bye!";
+static const int kLen3 = 4;
+static const char kMsg33[] = "bye!bye!";
+static const int kLen33 = kLen3 + kLen3;
+
+} // anonymous namespace
+
+namespace net {
+
+class SpdyProxyClientSocketTest : public PlatformTest {
+ public:
+ SpdyProxyClientSocketTest();
+
+ virtual void TearDown();
+
+ protected:
+ void Initialize(MockRead* reads, size_t reads_count, MockWrite* writes,
+ size_t writes_count);
+ spdy::SpdyFrame* ConstructConnectRequestFrame();
+ spdy::SpdyFrame* ConstructConnectAuthRequestFrame();
+ spdy::SpdyFrame* ConstructConnectReplyFrame();
+ spdy::SpdyFrame* ConstructConnectAuthReplyFrame();
+ spdy::SpdyFrame* ConstructConnectErrorReplyFrame();
+ spdy::SpdyFrame* ConstructBodyFrame(const char* data, int length);
+ scoped_refptr<IOBufferWithSize> CreateBuffer(const char* data, int size);
+ void AssertConnectSucceeds();
+ void AssertConnectionEstablished();
+ void AssertSyncReadEquals(const char* data, int len);
+ void AssertAsyncReadEquals(const char* data, int len);
+ void AssertAsyncWriteSucceeds(const char* data, int len);
+ void AssertAsyncWriteWithReadsSucceeds(const char* data, int len,
+ int num_reads);
+
+ void AddAuthToCache() {
+ const string16 kFoo(ASCIIToUTF16("foo"));
+ const string16 kBar(ASCIIToUTF16("bar"));
+ session_->auth_cache()->Add(GURL(kProxyUrl), "MyRealm1", "Basic",
+ "Basic realm=MyRealm1", kFoo, kBar, "/");
+ }
+
+ scoped_ptr<SpdyProxyClientSocket> sock_;
+ TestCompletionCallback callback_;
+
+ private:
+ scoped_refptr<HttpNetworkSession> session_;
+ scoped_refptr<OrderedSocketData> data_;
+ SpdySessionDependencies session_deps_;
+ MockConnect connect_data_;
+ scoped_refptr<SpdySession> spdy_session_;
+ scoped_refptr<SpdyStream> spdy_stream_;
+ spdy::SpdyFramer framer_;
+
+ std::string user_agent_;
+ GURL url_;
+ HostPortPair proxy_host_port_;
+ HostPortPair endpoint_host_port_pair_;
+ ProxyServer proxy_;
+ HostPortProxyPair endpoint_host_port_proxy_pair_;
+ scoped_refptr<TCPSocketParams> tcp_params_;
+
+ DISALLOW_COPY_AND_ASSIGN(SpdyProxyClientSocketTest);
+};
+
+SpdyProxyClientSocketTest::SpdyProxyClientSocketTest()
+ : sock_(NULL),
+ callback_(),
+ session_(NULL),
+ data_(NULL),
+ session_deps_(),
+ connect_data_(false, OK),
+ spdy_session_(NULL),
+ spdy_stream_(NULL),
+ framer_(),
+ user_agent_(kUserAgent),
+ url_(kUrl),
+ proxy_host_port_(kProxyHost, kProxyPort),
+ endpoint_host_port_pair_(kOriginHost, kOriginPort),
+ proxy_(ProxyServer::SCHEME_HTTPS, proxy_host_port_),
+ endpoint_host_port_proxy_pair_(endpoint_host_port_pair_, proxy_),
+ tcp_params_(new TCPSocketParams(proxy_host_port_, LOWEST, url_, false)) {
+}
+
+void SpdyProxyClientSocketTest::TearDown() {
+ if (session_ != NULL)
+ session_->spdy_session_pool()->CloseAllSessions();
+
+ spdy::SpdyFramer::set_enable_compression_default(true);
+ // Empty the current queue.
+ MessageLoop::current()->RunAllPending();
+ PlatformTest::TearDown();
+}
+
+void SpdyProxyClientSocketTest::Initialize(MockRead* reads,
+ size_t reads_count,
+ MockWrite* writes,
+ size_t writes_count) {
+ data_ = new OrderedSocketData(reads, reads_count, writes, writes_count);
+ data_->set_connect_data(connect_data_);
+
+ session_deps_.socket_factory->AddSocketDataProvider(data_.get());
+ session_deps_.host_resolver->set_synchronous_mode(true);
+
+ session_ = SpdySessionDependencies::SpdyCreateSession(&session_deps_);
+ SpdySession::SetSSLMode(false);
+ spdy::SpdyFramer::set_enable_compression_default(false);
+
+ // Creates a new spdy session
+ spdy_session_ =
+ session_->spdy_session_pool()->Get(endpoint_host_port_proxy_pair_,
+ session_->mutable_spdy_settings(),
+ BoundNetLog());
+
+ // Perform the TCP connect
+ scoped_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
+ EXPECT_EQ(OK,
+ connection->Init(endpoint_host_port_pair_.ToString(), tcp_params_,
+ LOWEST, NULL, session_->tcp_socket_pool(),
+ BoundNetLog()));
+ spdy_session_->InitializeWithSocket(connection.release(), false, OK);
+
+ // Create the SPDY Stream
+ ASSERT_EQ(
+ OK,
+ spdy_session_->CreateStream(url_, LOWEST, &spdy_stream_, BoundNetLog(),
+ NULL));
+
+ // Create the SpdyProxyClientSocket
+ sock_.reset(
+ new SpdyProxyClientSocket(spdy_stream_, user_agent_,
+ endpoint_host_port_pair_, url_,
+ proxy_host_port_, session_->auth_cache(),
+ session_->http_auth_handler_factory()));
+}
+
+scoped_refptr<IOBufferWithSize> SpdyProxyClientSocketTest::CreateBuffer(
+ const char* data, int size) {
+ scoped_refptr<IOBufferWithSize> buf(new IOBufferWithSize(size));
+ memcpy(buf->data(), data, size);
+ return buf;
+}
+
+void SpdyProxyClientSocketTest::AssertConnectSucceeds() {
+ ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_));
+ ASSERT_EQ(OK, callback_.WaitForResult());
+}
+
+void SpdyProxyClientSocketTest::AssertConnectionEstablished() {
+ const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
+ ASSERT_TRUE(response != NULL);
+ ASSERT_EQ(200, response->headers->response_code());
+ ASSERT_EQ("Connection Established", response->headers->GetStatusText());
+}
+
+void SpdyProxyClientSocketTest::AssertSyncReadEquals(const char* data,
+ int len) {
+ scoped_refptr<IOBuffer> buf(new IOBuffer(len));
+ ASSERT_EQ(len, sock_->Read(buf, len, NULL));
+ ASSERT_EQ(std::string(data, len), std::string(buf->data(), len));
+ ASSERT_TRUE(sock_->IsConnected());
+}
+
+void SpdyProxyClientSocketTest::AssertAsyncReadEquals(const char* data,
+ int len) {
+ // Issue the read, which will be completed asynchronously
+ scoped_refptr<IOBuffer> buf(new IOBuffer(len));
+ ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, len, &callback_));
+ EXPECT_TRUE(sock_->IsConnected());
+
+ // Dummy write to un-block the read
+ AssertAsyncWriteSucceeds(kMsg2, kLen2);
+ EXPECT_TRUE(sock_->IsConnected());
+
+ // Now the read will return
+ EXPECT_EQ(len, callback_.WaitForResult());
+ ASSERT_EQ(std::string(data, len), std::string(buf->data(), len));
+}
+
+void SpdyProxyClientSocketTest::AssertAsyncWriteSucceeds(const char* data,
+ int len) {
+ AssertAsyncWriteWithReadsSucceeds(data, len, 0);
+}
+
+void SpdyProxyClientSocketTest::AssertAsyncWriteWithReadsSucceeds(
+ const char* data, int len, int num_reads) {
+ scoped_refptr<IOBufferWithSize> buf(CreateBuffer(data, len));
+
+ TestCompletionCallback callback;
+ EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &callback));
+
+ // Dummy reads to un-block the writes
+ for (int i = 0; i < num_reads; i++) {
+ AssertSyncReadEquals(kMsg2, kLen2);
+ }
+
+ callback.WaitForResult();
+}
+
+// Constructs a standard SPDY SYN_STREAM frame for a CONNECT request.
+spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectRequestFrame() {
+ const SpdyHeaderInfo kSynStartHeader = {
+ spdy::SYN_STREAM,
+ kStreamId,
+ 0,
+ net::ConvertRequestPriorityToSpdyPriority(LOWEST),
+ spdy::CONTROL_FLAG_NONE,
+ false,
+ spdy::INVALID,
+ NULL,
+ 0,
+ spdy::DATA_FLAG_NONE
+ };
+ const char* const kConnectHeaders[] = {
+ "method", "CONNECT",
+ "url", kOriginHostPort,
+ "host", kOriginHost,
+ "user-agent", kUserAgent,
+ "version", "HTTP/1.1",
+ "proxy-connection", "keep-alive",
+ };
+ return ConstructSpdyPacket(
+ kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2);
+}
+
+// Constructs a SPDY SYN_STREAM frame for a CONNECT request which includes
+// Proxy-Authorization headers.
+spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthRequestFrame() {
+ const SpdyHeaderInfo kSynStartHeader = {
+ spdy::SYN_STREAM,
+ kStreamId,
+ 0,
+ net::ConvertRequestPriorityToSpdyPriority(LOWEST),
+ spdy::CONTROL_FLAG_NONE,
+ false,
+ spdy::INVALID,
+ NULL,
+ 0,
+ spdy::DATA_FLAG_NONE
+ };
+ const char* const kConnectHeaders[] = {
+ "method", "CONNECT",
+ "url", kOriginHostPort,
+ "host", kOriginHost,
+ "user-agent", kUserAgent,
+ "version", "HTTP/1.1",
+ "proxy-authorization", "Basic Zm9vOmJhcg==",
+ "proxy-connection", "keep-alive",
+ };
+ return ConstructSpdyPacket(
+ kSynStartHeader, NULL, 0, kConnectHeaders, arraysize(kConnectHeaders)/2);
+}
+
+// Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
+spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectReplyFrame() {
+ const char* const kStandardReplyHeaders[] = {
+ "status", "200 Connection Established",
+ "version", "HTTP/1.1"
+ };
+ return ConstructSpdyControlFrame(NULL,
+ 0,
+ false,
+ kStreamId,
+ LOWEST,
+ spdy::SYN_REPLY,
+ spdy::CONTROL_FLAG_NONE,
+ kStandardReplyHeaders,
+ arraysize(kStandardReplyHeaders));
+}
+
+// Constructs a standard SPDY SYN_REPLY frame to match the SPDY CONNECT.
+spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectAuthReplyFrame() {
+ const char* const kStandardReplyHeaders[] = {
+ "status", "407 Proxy Authentication Required",
+ "version", "HTTP/1.1",
+ "proxy-authenticate", "Basic realm=\"MyRealm1\"",
+ };
+
+ return ConstructSpdyControlFrame(NULL,
+ 0,
+ false,
+ kStreamId,
+ LOWEST,
+ spdy::SYN_REPLY,
+ spdy::CONTROL_FLAG_NONE,
+ kStandardReplyHeaders,
+ arraysize(kStandardReplyHeaders));
+}
+
+// Constructs a SPDY SYN_REPLY frame with an HTTP 500 error.
+spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructConnectErrorReplyFrame() {
+ const char* const kStandardReplyHeaders[] = {
+ "status", "500 Internal Server Error",
+ "version", "HTTP/1.1",
+ };
+
+ return ConstructSpdyControlFrame(NULL,
+ 0,
+ false,
+ kStreamId,
+ LOWEST,
+ spdy::SYN_REPLY,
+ spdy::CONTROL_FLAG_NONE,
+ kStandardReplyHeaders,
+ arraysize(kStandardReplyHeaders));
+}
+
+spdy::SpdyFrame* SpdyProxyClientSocketTest::ConstructBodyFrame(const char* data,
+ int length) {
+ return framer_.CreateDataFrame(kStreamId, data, length, spdy::DATA_FLAG_NONE);
+}
+
+// ----------- Connect
+
+TEST_F(SpdyProxyClientSocketTest, ConnectSendsCorrectRequest) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 0),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 1),
+ MockRead(true, 0, 0), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ ASSERT_FALSE(sock_->IsConnected());
+
+ AssertConnectSucceeds();
+
+ AssertConnectionEstablished();
+}
+
+TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthRequested) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 0),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 1),
+ MockRead(true, 0, 0), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_));
+ EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult());
+
+ const HttpResponseInfo* response = sock_->GetConnectResponseInfo();
+ ASSERT_TRUE(response != NULL);
+ ASSERT_EQ(407, response->headers->response_code());
+ ASSERT_EQ("Proxy Authentication Required",
+ response->headers->GetStatusText());
+}
+
+TEST_F(SpdyProxyClientSocketTest, ConnectWithAuthCredentials) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectAuthRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 0),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 1),
+ MockRead(true, 0, 0), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+ AddAuthToCache();
+
+ EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_));
+ EXPECT_EQ(OK, callback_.WaitForResult());
+
+ AssertConnectionEstablished();
+}
+
+TEST_F(SpdyProxyClientSocketTest, ConnectFails) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 0),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ MockRead(true, 0, 0), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ ASSERT_FALSE(sock_->IsConnected());
+
+ ASSERT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_));
+ ASSERT_EQ(ERR_CONNECTION_CLOSED, callback_.WaitForResult());
+
+ ASSERT_FALSE(sock_->IsConnected());
+}
+
+// ----------- WasEverUsed
+
+TEST_F(SpdyProxyClientSocketTest, WasEverUsedReturnsCorrectValues) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 0),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 1),
+ MockRead(true, 0, 0), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ EXPECT_FALSE(sock_->WasEverUsed());
+ AssertConnectSucceeds();
+ EXPECT_TRUE(sock_->WasEverUsed());
+ sock_->Disconnect();
+ EXPECT_TRUE(sock_->WasEverUsed());
+}
+
+// ----------- GetPeerAddress
+
+TEST_F(SpdyProxyClientSocketTest, GetPeerAddressReturnsCorrectValues) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ MockWrite(true, 0, 3), // EOF
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ MockRead(false, 0, 4), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ net::AddressList addr;
+ EXPECT_EQ(ERR_UNEXPECTED, sock_->GetPeerAddress(&addr));
+ AssertConnectSucceeds();
+ EXPECT_TRUE(sock_->IsConnected());
+ EXPECT_EQ(OK, sock_->GetPeerAddress(&addr));
+ sock_->Disconnect();
+ EXPECT_EQ(ERR_UNEXPECTED, sock_->GetPeerAddress(&addr));
+}
+
+// ----------- Write
+
+TEST_F(SpdyProxyClientSocketTest, WriteSendsDataInDataFrame) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 0),
+ CreateMockWrite(*msg1, 3),
+ CreateMockWrite(*msg2, 4),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ MockRead(true, 0, 6), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ AssertAsyncWriteSucceeds(kMsg1, kLen1);
+ AssertAsyncWriteSucceeds(kMsg2, kLen2);
+}
+
+// ----------- Read
+
+TEST_F(SpdyProxyClientSocketTest, ReadReadsDataInDataFrame) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*msg1, 3),
+ CreateMockRead(*msg2, 4),
+ MockRead(true, 0, 6), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ AssertSyncReadEquals(kMsg1, kLen1);
+ AssertSyncReadEquals(kMsg2, kLen2);
+}
+
+TEST_F(SpdyProxyClientSocketTest, ReadAuthResponseBody) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectAuthReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*msg1, 3),
+ CreateMockRead(*msg2, 4),
+ MockRead(true, 0, 6), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_));
+ EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult());
+ // EXPECT_EQ(ERR_PROXY_AUTH_REQUESTED, callback_.WaitForResult());
+
+ AssertSyncReadEquals(kMsg1, kLen1);
+ AssertSyncReadEquals(kMsg2, kLen2);
+}
+
+TEST_F(SpdyProxyClientSocketTest, ReadErrorResponseBody) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectErrorReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*msg1, 3),
+ CreateMockRead(*msg2, 4),
+ MockRead(true, 0, 6), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ EXPECT_EQ(ERR_IO_PENDING, sock_->Connect(&callback_));
+ EXPECT_EQ(ERR_TUNNEL_CONNECTION_FAILED, callback_.WaitForResult());
+
+ AssertSyncReadEquals(kMsg1, kLen1);
+ AssertSyncReadEquals(kMsg2, kLen2);
+}
+
+// ----------- Reads and Writes
+
+TEST_F(SpdyProxyClientSocketTest, AsyncReadAroundWrite) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ CreateMockWrite(*msg2, 4), // write to un-cork the read
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*msg1, 3), // sync read
+ CreateMockRead(*msg3, 5, true), // async read
+ MockRead(true, 0, 9), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ AssertSyncReadEquals(kMsg1, kLen1);
+
+ AssertAsyncReadEquals(kMsg3, kLen3);
+}
+
+TEST_F(SpdyProxyClientSocketTest, AsyncWriteAroundRead) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ CreateMockWrite(*msg1, 4),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*msg2, 3), // sync read (which will un-cork the write)
+ MockRead(true, 0, 5), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ AssertAsyncWriteWithReadsSucceeds(kMsg1, kLen1, 1);
+}
+
+TEST_F(SpdyProxyClientSocketTest, Mixed) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ CreateMockWrite(*msg2, 4), // write to un-cork the read
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*msg1, 3), // sync read
+ CreateMockRead(*msg3, 5, true), // async read
+ MockRead(true, 0, 9), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ AssertSyncReadEquals(kMsg1, kLen1);
+ AssertAsyncReadEquals(kMsg3, kLen3);
+}
+
+TEST_F(SpdyProxyClientSocketTest, MultipleShortReads) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*msg1, 3), // sync read
+ CreateMockRead(*msg3, 4), // sync read
+ CreateMockRead(*msg3, 5), // sync read
+ MockRead(true, 0, 8), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ AssertSyncReadEquals(kMsg1, kLen1);
+ // The payload from two data frames, each with kMsg3 will be combined
+ // together into a single read().
+ AssertSyncReadEquals(kMsg33, kLen33);
+}
+
+TEST_F(SpdyProxyClientSocketTest, MultipleShortReadsThenMoreRead) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<spdy::SpdyFrame> msg3(ConstructBodyFrame(kMsg3, kLen3));
+ scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*msg1, 3), // sync read
+ CreateMockRead(*msg3, 4), // sync read
+ CreateMockRead(*msg3, 5), // sync read
+ CreateMockRead(*msg2, 5), // sync read
+ MockRead(true, 0, 8), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ AssertSyncReadEquals(kMsg1, kLen1);
+ // The payload from two data frames, each with kMsg3 will be combined
+ // together into a single read().
+ AssertSyncReadEquals(kMsg33, kLen33);
+ AssertSyncReadEquals(kMsg2, kLen2);
+}
+
+
+TEST_F(SpdyProxyClientSocketTest, LargeSplitRead) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ scoped_ptr<spdy::SpdyFrame> msg33(ConstructBodyFrame(kMsg33, kLen33));
+ scoped_ptr<spdy::SpdyFrame> msg2(ConstructBodyFrame(kMsg2, kLen2));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ CreateMockRead(*msg1, 3),
+ CreateMockRead(*msg33, 4),
+ MockRead(true, 0, 8), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ AssertSyncReadEquals(kMsg1, kLen1);
+ // The payload from the single large data frame will be read across
+ // two different reads.
+ AssertSyncReadEquals(kMsg3, kLen3);
+ AssertSyncReadEquals(kMsg3, kLen3);
+}
+
+TEST_F(SpdyProxyClientSocketTest, WriteLargeDataSplits) {
+ std::string chunk_data(kMaxSpdyFrameChunkSize, 'x');
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ scoped_ptr<spdy::SpdyFrame> chunk(ConstructBodyFrame(chunk_data.data(),
+ chunk_data.length()));
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ CreateMockWrite(*chunk, 3, false),
+ CreateMockWrite(*chunk, 4, false),
+ CreateMockWrite(*chunk, 5, false)
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ MockRead(true, 0, 7), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ std::string big_data(kMaxSpdyFrameChunkSize * 3, 'x');
+ AssertAsyncWriteSucceeds(big_data.data(), big_data.length());
+}
+
+// ----------- Reading/Writing on Closed socket
+
+// Reading from an already closed socket should return 0
+TEST_F(SpdyProxyClientSocketTest, ReadOnClosedSocketReturnsZero) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ MockRead(true, 0, 4), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ sock_->Disconnect();
+
+ ASSERT_EQ(0, sock_->Read(NULL, 1, NULL));
+ ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL));
+ ASSERT_EQ(ERR_CONNECTION_CLOSED, sock_->Read(NULL, 1, NULL));
+}
+
+// Calling Write() on a closed socket is an error
+TEST_F(SpdyProxyClientSocketTest, WriteOnClosedStream) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ scoped_ptr<spdy::SpdyFrame> msg1(ConstructBodyFrame(kMsg1, kLen1));
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ MockRead(false, 0, 3), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
+ EXPECT_EQ(ERR_CONNECTION_CLOSED, sock_->Write(buf, buf->size(), NULL));
+}
+
+// ----------- Pending read/write when closed
+
+// If the socket is closed with a pending Write(), the callback
+// should not be called.
+TEST_F(SpdyProxyClientSocketTest, DisconnectWithWritePending) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ MockWrite(true, 0, 3), // EOF
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ MockRead(false, 0, 4), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ EXPECT_TRUE(sock_->IsConnected());
+
+ scoped_refptr<IOBufferWithSize> buf(CreateBuffer(kMsg1, kLen1));
+ EXPECT_EQ(ERR_IO_PENDING, sock_->Write(buf, buf->size(), &callback_));
+
+ sock_->Disconnect();
+
+ EXPECT_FALSE(sock_->IsConnected());
+ EXPECT_FALSE(callback_.have_result());
+}
+
+// If the socket is closed with a pending Read(), the callback
+// should not be called.
+TEST_F(SpdyProxyClientSocketTest, DisconnectWithReadPending) {
+ scoped_ptr<spdy::SpdyFrame> conn(ConstructConnectRequestFrame());
+ MockWrite writes[] = {
+ CreateMockWrite(*conn, 1),
+ };
+
+ scoped_ptr<spdy::SpdyFrame> resp(ConstructConnectReplyFrame());
+ MockRead reads[] = {
+ CreateMockRead(*resp, 2),
+ MockRead(true, 0, 4), // EOF
+ };
+
+ Initialize(reads, arraysize(reads), writes, arraysize(writes));
+
+ AssertConnectSucceeds();
+
+ EXPECT_TRUE(sock_->IsConnected());
+
+ scoped_refptr<IOBuffer> buf(new IOBuffer(kLen1));
+ ASSERT_EQ(ERR_IO_PENDING, sock_->Read(buf, kLen1, &callback_));
+
+ sock_->Disconnect();
+
+ EXPECT_FALSE(sock_->IsConnected());
+ EXPECT_FALSE(callback_.have_result());
+}
+
+} // namespace net
Property changes on: net/spdy/spdy_proxy_client_socket_unittest.cc
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « net/spdy/spdy_proxy_client_socket.cc ('k') | net/spdy/spdy_session.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698