Chromium Code Reviews| Index: net/websockets/websocket_job_unittest.cc |
| diff --git a/net/websockets/websocket_job_unittest.cc b/net/websockets/websocket_job_unittest.cc |
| index e863faf00058eb10282454c341ce7f9f31bcad92..0b74e995934f688463574f402b2ab7b694d26de7 100644 |
| --- a/net/websockets/websocket_job_unittest.cc |
| +++ b/net/websockets/websocket_job_unittest.cc |
| @@ -19,9 +19,13 @@ |
| #include "net/base/sys_addrinfo.h" |
| #include "net/base/test_completion_callback.h" |
| #include "net/base/transport_security_state.h" |
| +#include "net/http/http_transaction_factory.h" |
| #include "net/proxy/proxy_service.h" |
| #include "net/socket/socket_test_util.h" |
| #include "net/socket_stream/socket_stream.h" |
| +#include "net/spdy/spdy_session.h" |
| +#include "net/spdy/spdy_test_util.h" |
| +#include "net/spdy/spdy_websocket_test_util.h" |
| #include "net/url_request/url_request_context.h" |
| #include "net/websockets/websocket_throttle.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| @@ -198,6 +202,65 @@ class MockURLRequestContext : public net::URLRequestContext { |
| scoped_refptr<net::TransportSecurityState> transport_security_state_; |
| }; |
| +class MockHttpTransactionFactory : public net::HttpTransactionFactory { |
| + public: |
| + MockHttpTransactionFactory(scoped_refptr<net::OrderedSocketData>& data) { |
| + data_ = data; |
| + data_->AddRef(); |
| + net::MockConnect connect_data(false, net::OK); |
| + data_->set_connect_data(connect_data); |
| + session_deps_.reset(new net::SpdySessionDependencies); |
| + session_deps_->socket_factory->AddSocketDataProvider(data_.get()); |
| + http_session_ = |
| + net::SpdySessionDependencies::SpdyCreateSession(session_deps_.get()); |
| + host_port_pair_.set_host("example.com"); |
| + host_port_pair_.set_port(80); |
| + host_port_proxy_pair_.first = host_port_pair_; |
| + host_port_proxy_pair_.second = net::ProxyServer::Direct(); |
| + net::SpdySessionPool* spdy_session_pool = |
| + http_session_->spdy_session_pool(); |
| + DCHECK(spdy_session_pool); |
| + EXPECT_FALSE(spdy_session_pool->HasSession(host_port_proxy_pair_)); |
| + session_ = |
| + spdy_session_pool->Get(host_port_proxy_pair_, net::BoundNetLog()); |
| + EXPECT_TRUE(spdy_session_pool->HasSession(host_port_proxy_pair_)); |
| + |
| + transport_params_ = new net::TransportSocketParams(host_port_pair_, |
| + net::MEDIUM, |
| + GURL(), |
| + false, |
| + false); |
| + net::ClientSocketHandle* connection = new net::ClientSocketHandle; |
| + EXPECT_EQ(net::OK, connection->Init(host_port_pair_.ToString(), |
| + transport_params_, |
| + net::MEDIUM, |
| + NULL, |
| + http_session_->transport_socket_pool(), |
| + net::BoundNetLog())); |
| + EXPECT_EQ(net::OK, |
| + session_->InitializeWithSocket(connection, false, net::OK)); |
| + } |
| + virtual int CreateTransaction(scoped_ptr<net::HttpTransaction>* trans) { |
| + NOTREACHED(); |
| + return net::ERR_UNEXPECTED; |
| + } |
| + virtual net::HttpCache* GetCache() { |
| + NOTREACHED(); |
| + return NULL; |
| + } |
| + virtual net::HttpNetworkSession* GetSession() { |
| + return http_session_.get(); |
| + } |
| + private: |
| + scoped_refptr<net::OrderedSocketData> data_; |
| + scoped_ptr<net::SpdySessionDependencies> session_deps_; |
| + scoped_refptr<net::HttpNetworkSession> http_session_; |
| + scoped_refptr<net::TransportSocketParams> transport_params_; |
| + scoped_refptr<net::SpdySession> session_; |
| + net::HostPortPair host_port_pair_; |
| + net::HostPortProxyPair host_port_proxy_pair_; |
| +}; |
| + |
| } |
| namespace net { |
| @@ -205,6 +268,7 @@ namespace net { |
| class WebSocketJobTest : public PlatformTest { |
| public: |
| virtual void SetUp() { |
| + spdy::SpdyFramer::set_enable_compression_default(false); |
| stream_type_ = STREAM_INVALID; |
| cookie_store_ = new MockCookieStore; |
| context_ = new MockURLRequestContext(cookie_store_.get()); |
| @@ -242,6 +306,14 @@ class WebSocketJobTest : public PlatformTest { |
| stream_type_ = stream_type; |
| websocket_ = new WebSocketJob(delegate); |
| + if (stream_type == STREAM_MOCK_SOCKET) |
| + socket_ = new MockSocketStream(url, websocket_.get()); |
| + |
| + if (stream_type == STREAM_SPDY_WEBSOCKET) { |
| + http_factory_.reset(new MockHttpTransactionFactory(data_)); |
| + context_->set_http_transaction_factory(http_factory_.get()); |
| + } |
| + |
| if (stream_type == STREAM_SOCKET || |
| stream_type == STREAM_SPDY_WEBSOCKET) { |
| ssl_config_service_ = new MockSSLConfigService(); |
| @@ -250,26 +322,14 @@ class WebSocketJobTest : public PlatformTest { |
| context_->set_proxy_service(proxy_service_.get()); |
| host_resolver_.reset(new net::MockHostResolver); |
| context_->set_host_resolver(host_resolver_.get()); |
| - } |
| - switch (stream_type) { |
| - case STREAM_INVALID: |
| - NOTREACHED(); |
| - break; |
| - case STREAM_MOCK_SOCKET: |
| - socket_ = new MockSocketStream(url, websocket_.get()); |
| - break; |
| - case STREAM_SOCKET: |
| - socket_ = new SocketStream(url, websocket_.get()); |
| - socket_factory_.reset(new MockClientSocketFactory); |
| - DCHECK(data_.get()); |
| - socket_factory_->AddSocketDataProvider(data_.get()); |
| - socket_->SetClientSocketFactory(socket_factory_.get()); |
| - break; |
| - case STREAM_SPDY_WEBSOCKET: |
| - // TODO(toyoshim): Support SpdyWebSocketStream. |
| - break; |
| + socket_ = new SocketStream(url, websocket_.get()); |
| + socket_factory_.reset(new MockClientSocketFactory); |
| + DCHECK(data_.get()); |
| + socket_factory_->AddSocketDataProvider(data_.get()); |
| + socket_->SetClientSocketFactory(socket_factory_.get()); |
| } |
|
Yuta Kitamura
2011/07/08 07:40:21
The three blocks above sound a bit confusing...
H
Takashi Toyoshima
2011/07/08 08:35:14
Thanks.
New one looks fine!
|
| + |
| websocket_->InitSocketStream(socket_.get()); |
| websocket_->set_context(context_.get()); |
| struct addrinfo addr; |
| @@ -324,6 +384,7 @@ class WebSocketJobTest : public PlatformTest { |
| void TestHSTSUpgrade(); |
| void TestInvalidSendData(); |
| void TestConnectByWebSocket(); |
| + void TestConnectBySpdy(bool use_spdy); |
| StreamType stream_type_; |
| scoped_refptr<MockCookieStore> cookie_store_; |
| @@ -336,6 +397,7 @@ class WebSocketJobTest : public PlatformTest { |
| scoped_refptr<MockSSLConfigService> ssl_config_service_; |
| scoped_ptr<net::ProxyService> proxy_service_; |
| scoped_ptr<net::MockHostResolver> host_resolver_; |
| + scoped_ptr<MockHttpTransactionFactory> http_factory_; |
| static const char kHandshakeRequestWithoutCookie[]; |
| static const char kHandshakeRequestWithCookie[]; |
| @@ -344,6 +406,8 @@ class WebSocketJobTest : public PlatformTest { |
| static const char kHandshakeResponseWithCookie[]; |
| static const char kDataHello[]; |
| static const char kDataWorld[]; |
| + static const char* const kHandshakeRequestForSpdy[]; |
| + static const char* const kHandshakeResponseForSpdy[]; |
| static const size_t kHandshakeRequestWithoutCookieLength; |
| static const size_t kHandshakeRequestWithCookieLength; |
| static const size_t kHandshakeRequestWithFilteredCookieLength; |
| @@ -416,6 +480,22 @@ const char WebSocketJobTest::kDataHello[] = "Hello, "; |
| const char WebSocketJobTest::kDataWorld[] = "World!\n"; |
| +// TODO(toyoshim): I should clarify which WebSocket headers for handshake must |
| +// be exported to SPDY SYN_STREAM and SYN_REPLY. |
| +// Because it depends on HyBi versions, just define it as follow for now. |
| +const char* const WebSocketJobTest::kHandshakeRequestForSpdy[] = { |
| + "host", "example.com", |
| + "origin", "http://example.com", |
| + "sec-websocket-protocol", "sample", |
| + "url", "ws://example.com/demo" |
| +}; |
| + |
| +const char* const WebSocketJobTest::kHandshakeResponseForSpdy[] = { |
| + "sec-websocket-origin", "http://example.com", |
| + "sec-websocket-location", "ws://example.com/demo", |
| + "sec-websocket-protocol", "sample", |
| +}; |
| + |
| const size_t WebSocketJobTest::kHandshakeRequestWithoutCookieLength = |
| arraysize(kHandshakeRequestWithoutCookie) - 1; |
| const size_t WebSocketJobTest::kHandshakeRequestWithCookieLength = |
| @@ -624,7 +704,6 @@ void WebSocketJobTest::TestInvalidSendData() { |
| // OrderedSocketData provide socket level verifiation by checking out-going |
| // packets in comparison with the MockWrite array and emulating in-coming |
| // packets with MockRead array. |
| -// TODO(toyoshim): Add tests which verify protocol switch and ERR_IO_PENDING. |
| void WebSocketJobTest::TestConnectByWebSocket() { |
| // This is a test for verifying cooperation between WebSocketJob and |
| @@ -671,6 +750,94 @@ void WebSocketJobTest::TestConnectByWebSocket() { |
| EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState()); |
| } |
| +void WebSocketJobTest::TestConnectBySpdy(bool use_spdy) { |
| + // This is a test for verifying cooperation between WebSocketJob and |
| + // SocketStream in the situation we have SPDY session to the server. |
| + MockWrite writes_websocket[] = { |
| + MockWrite(true, |
| + kHandshakeRequestWithoutCookie, |
| + kHandshakeRequestWithoutCookieLength, |
| + 1), |
| + MockWrite(true, |
| + kDataHello, |
| + kDataHelloLength, |
| + 3) |
| + }; |
| + MockRead reads_websocket[] = { |
| + MockRead(true, |
| + kHandshakeResponseWithoutCookie, |
| + kHandshakeResponseWithoutCookieLength, |
| + 2), |
| + MockRead(true, |
| + kDataWorld, |
| + kDataWorldLength, |
| + 4), |
| + MockRead(false, 0, 5) // EOF |
| + }; |
| + |
| + const spdy::SpdyStreamId kStreamId = 1; |
| + scoped_ptr<spdy::SpdyFrame> request_frame( |
| + ConstructSpdyWebSocketHandshakeRequestFrame( |
| + kHandshakeRequestForSpdy, |
| + arraysize(kHandshakeRequestForSpdy) / 2, |
| + kStreamId, |
| + MEDIUM)); |
| + scoped_ptr<spdy::SpdyFrame> response_frame( |
| + ConstructSpdyWebSocketHandshakeResponseFrame( |
| + kHandshakeResponseForSpdy, |
| + arraysize(kHandshakeResponseForSpdy) / 2, |
| + kStreamId, |
| + MEDIUM)); |
| + scoped_ptr<spdy::SpdyFrame> data_hello_frame( |
| + ConstructSpdyWebSocketDataFrame( |
| + kDataHello, |
| + kDataHelloLength, |
| + kStreamId, |
| + false)); |
| + scoped_ptr<spdy::SpdyFrame> data_world_frame( |
| + ConstructSpdyWebSocketDataFrame( |
| + kDataWorld, |
| + kDataWorldLength, |
| + kStreamId, |
| + false)); |
| + MockWrite writes_spdy[] = { |
| + CreateMockWrite(*request_frame.get(), 1), |
| + CreateMockWrite(*data_hello_frame.get(), 3), |
| + }; |
| + MockRead reads_spdy[] = { |
| + CreateMockRead(*response_frame.get(), 2), |
| + CreateMockRead(*data_world_frame.get(), 4), |
| + MockRead(false, 0, 5) // EOF |
| + }; |
| + |
| + if (use_spdy) |
| + data_ = new OrderedSocketData( |
| + reads_spdy, arraysize(reads_spdy), |
| + writes_spdy, arraysize(writes_spdy)); |
| + else |
| + data_ = new OrderedSocketData( |
| + reads_websocket, arraysize(reads_websocket), |
| + writes_websocket, arraysize(writes_websocket)); |
| + |
| + GURL url("ws://example.com/demo"); |
| + MockSocketStreamDelegate delegate; |
| + WebSocketJobTest* test = this; |
| + delegate.SetOnConnected( |
| + NewCallback(test, &WebSocketJobTest::DoSendRequest)); |
| + delegate.SetOnReceivedData( |
| + NewCallback(test, &WebSocketJobTest::DoSendData)); |
| + delegate.SetOnClose( |
| + NewCallback(test, &WebSocketJobTest::DoSync)); |
| + InitWebSocketJob(url, &delegate, STREAM_SPDY_WEBSOCKET); |
| + |
| + websocket_->Connect(); |
| + EXPECT_EQ(OK, WaitForResult()); |
| + |
| + EXPECT_TRUE(data_->at_read_eof()); |
| + EXPECT_TRUE(data_->at_write_eof()); |
| + EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState()); |
| +} |
| + |
| // Execute tests in both spdy-disabled mode and spdy-enabled mode. |
| TEST_F(WebSocketJobTest, SimpleHandshake) { |
| WebSocketJob::set_websocket_over_spdy_enabled(false); |
| @@ -742,4 +909,17 @@ TEST_F(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) { |
| TestConnectByWebSocket(); |
| } |
| +TEST_F(WebSocketJobTest, ConnectBySpdy) { |
| + WebSocketJob::set_websocket_over_spdy_enabled(false); |
| + TestConnectBySpdy(false); |
| +} |
| + |
| +TEST_F(WebSocketJobTest, ConnectBySpdySpdyEnabled) { |
| + WebSocketJob::set_websocket_over_spdy_enabled(true); |
| + TestConnectBySpdy(true); |
| +} |
| + |
| +// TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation. |
| +// TODO(toyoshim,yutak): Add tests to verify closing handshake. |
| + |
| } // namespace net |