diff options
author | toyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-06 12:30:07 +0000 |
---|---|---|
committer | toyoshim@chromium.org <toyoshim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-06 12:30:07 +0000 |
commit | 71a356cbc5fd61fa36e726a0ab613fe760e9256b (patch) | |
tree | b6dc429b48e9b10787a504e0c09181662b5c9547 /net/websockets | |
parent | 85c1dcebfbb0e3f2696086a6e6ad6156af0afad5 (diff) | |
download | chromium_src-71a356cbc5fd61fa36e726a0ab613fe760e9256b.zip chromium_src-71a356cbc5fd61fa36e726a0ab613fe760e9256b.tar.gz chromium_src-71a356cbc5fd61fa36e726a0ab613fe760e9256b.tar.bz2 |
WebSocket: Add connection test on WebSocketJobTest
- Move local test utility classes into anonymous namespace.
- Add new connection test.
BUG=NONE
TEST=net_unittests --gtest_filter=WebSocketJobTest\*
Review URL: http://codereview.chromium.org/7193035
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@91550 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/websockets')
-rw-r--r-- | net/websockets/websocket_job_unittest.cc | 280 |
1 files changed, 233 insertions, 47 deletions
diff --git a/net/websockets/websocket_job_unittest.cc b/net/websockets/websocket_job_unittest.cc index ff20864..e863faf 100644 --- a/net/websockets/websocket_job_unittest.cc +++ b/net/websockets/websocket_job_unittest.cc @@ -11,10 +11,16 @@ #include "base/string_split.h" #include "base/string_util.h" #include "googleurl/src/gurl.h" +#include "net/base/completion_callback.h" #include "net/base/cookie_store.h" +#include "net/base/mock_host_resolver.h" #include "net/base/net_errors.h" +#include "net/base/ssl_config_service.h" #include "net/base/sys_addrinfo.h" +#include "net/base/test_completion_callback.h" #include "net/base/transport_security_state.h" +#include "net/proxy/proxy_service.h" +#include "net/socket/socket_test_util.h" #include "net/socket_stream/socket_stream.h" #include "net/url_request/url_request_context.h" #include "net/websockets/websocket_throttle.h" @@ -22,11 +28,11 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/platform_test.h" -namespace net { +namespace { -class MockSocketStream : public SocketStream { +class MockSocketStream : public net::SocketStream { public: - MockSocketStream(const GURL& url, SocketStream::Delegate* delegate) + MockSocketStream(const GURL& url, net::SocketStream::Delegate* delegate) : SocketStream(url, delegate) {} virtual ~MockSocketStream() {} @@ -51,7 +57,7 @@ class MockSocketStream : public SocketStream { std::string sent_data_; }; -class MockSocketStreamDelegate : public SocketStream::Delegate { +class MockSocketStreamDelegate : public net::SocketStream::Delegate { public: MockSocketStreamDelegate() : amount_sent_(0), allow_all_cookies_(true) {} @@ -60,25 +66,46 @@ class MockSocketStreamDelegate : public SocketStream::Delegate { } virtual ~MockSocketStreamDelegate() {} - virtual void OnConnected(SocketStream* socket, + void SetOnConnected(Callback0::Type* callback) { + on_connected_.reset(callback); + } + void SetOnSentData(Callback0::Type* callback) { + on_sent_data_.reset(callback); + } + void SetOnReceivedData(Callback0::Type* callback) { + on_received_data_.reset(callback); + } + void SetOnClose(Callback0::Type* callback) { + on_close_.reset(callback); + } + + virtual void OnConnected(net::SocketStream* socket, int max_pending_send_allowed) { + if (on_connected_.get()) + on_connected_->Run(); } - virtual void OnSentData(SocketStream* socket, int amount_sent) { + virtual void OnSentData(net::SocketStream* socket, int amount_sent) { amount_sent_ += amount_sent; + if (on_sent_data_.get()) + on_sent_data_->Run(); } - virtual void OnReceivedData(SocketStream* socket, + virtual void OnReceivedData(net::SocketStream* socket, const char* data, int len) { received_data_ += std::string(data, len); + if (on_received_data_.get()) + on_received_data_->Run(); } - virtual void OnClose(SocketStream* socket) { + virtual void OnClose(net::SocketStream* socket) { + if (on_close_.get()) + on_close_->Run(); } - virtual bool CanGetCookies(SocketStream* socket, const GURL& url) { + virtual bool CanGetCookies(net::SocketStream* socket, const GURL& url) { return allow_all_cookies_; } - virtual bool CanSetCookie(SocketStream* request, + virtual bool CanSetCookie(net::SocketStream* request, const GURL& url, const std::string& cookie_line, - CookieOptions* options) { + net::CookieOptions* options) { return allow_all_cookies_; } @@ -89,20 +116,24 @@ class MockSocketStreamDelegate : public SocketStream::Delegate { int amount_sent_; bool allow_all_cookies_; std::string received_data_; + scoped_ptr<Callback0::Type> on_connected_; + scoped_ptr<Callback0::Type> on_sent_data_; + scoped_ptr<Callback0::Type> on_received_data_; + scoped_ptr<Callback0::Type> on_close_; }; -class MockCookieStore : public CookieStore { +class MockCookieStore : public net::CookieStore { public: struct Entry { GURL url; std::string cookie_line; - CookieOptions options; + net::CookieOptions options; }; MockCookieStore() {} virtual bool SetCookieWithOptions(const GURL& url, const std::string& cookie_line, - const CookieOptions& options) { + const net::CookieOptions& options) { Entry entry; entry.url = url; entry.cookie_line = cookie_line; @@ -110,8 +141,9 @@ class MockCookieStore : public CookieStore { entries_.push_back(entry); return true; } - virtual std::string GetCookiesWithOptions(const GURL& url, - const CookieOptions& options) { + virtual std::string GetCookiesWithOptions( + const GURL& url, + const net::CookieOptions& options) { std::string result; for (size_t i = 0; i < entries_.size(); i++) { Entry &entry = entries_[i]; @@ -125,14 +157,14 @@ class MockCookieStore : public CookieStore { return result; } virtual void GetCookiesWithInfo(const GURL& url, - const CookieOptions& options, + const net::CookieOptions& options, std::string* cookie_line, std::vector<CookieInfo>* cookie_infos) { NOTREACHED(); } virtual void DeleteCookie(const GURL& url, const std::string& cookie_name) {} - virtual CookieMonster* GetCookieMonster() { return NULL; } + virtual net::CookieMonster* GetCookieMonster() { return NULL; } const std::vector<Entry>& entries() const { return entries_; } @@ -143,13 +175,18 @@ class MockCookieStore : public CookieStore { std::vector<Entry> entries_; }; -class MockURLRequestContext : public URLRequestContext { +class MockSSLConfigService : public net::SSLConfigService { public: - explicit MockURLRequestContext(CookieStore* cookie_store) { + virtual void GetSSLConfig(net::SSLConfig* config) {}; +}; + +class MockURLRequestContext : public net::URLRequestContext { + public: + explicit MockURLRequestContext(net::CookieStore* cookie_store) { set_cookie_store(cookie_store); - transport_security_state_ = new TransportSecurityState(std::string()); + transport_security_state_ = new net::TransportSecurityState(std::string()); set_transport_security_state(transport_security_state_.get()); - TransportSecurityState::DomainState state; + net::TransportSecurityState::DomainState state; state.expiry = base::Time::Now() + base::TimeDelta::FromSeconds(1000); transport_security_state_->EnableHost("upgrademe.com", state); } @@ -158,12 +195,17 @@ class MockURLRequestContext : public URLRequestContext { friend class base::RefCountedThreadSafe<MockURLRequestContext>; virtual ~MockURLRequestContext() {} - scoped_refptr<TransportSecurityState> transport_security_state_; + scoped_refptr<net::TransportSecurityState> transport_security_state_; }; +} + +namespace net { + class WebSocketJobTest : public PlatformTest { public: virtual void SetUp() { + stream_type_ = STREAM_INVALID; cookie_store_ = new MockCookieStore; context_ = new MockURLRequestContext(cookie_store_.get()); } @@ -173,10 +215,61 @@ class WebSocketJobTest : public PlatformTest { websocket_ = NULL; socket_ = NULL; } + void DoSendRequest() { + EXPECT_TRUE(websocket_->SendData(kHandshakeRequestWithoutCookie, + kHandshakeRequestWithoutCookieLength)); + } + void DoSendData() { + if (received_data().size() == kHandshakeResponseWithoutCookieLength) + websocket_->SendData(kDataHello, kDataHelloLength); + } + void DoSync() { + sync_callback_.Run(OK); + } + int WaitForResult() { + return sync_callback_.WaitForResult(); + } protected: - void InitWebSocketJob(const GURL& url, MockSocketStreamDelegate* delegate) { + enum StreamType { + STREAM_INVALID, + STREAM_MOCK_SOCKET, + STREAM_SOCKET, + STREAM_SPDY_WEBSOCKET, + }; + void InitWebSocketJob(const GURL& url, + MockSocketStreamDelegate* delegate, + StreamType stream_type) { + stream_type_ = stream_type; websocket_ = new WebSocketJob(delegate); - socket_ = new MockSocketStream(url, websocket_.get()); + + if (stream_type == STREAM_SOCKET || + stream_type == STREAM_SPDY_WEBSOCKET) { + ssl_config_service_ = new MockSSLConfigService(); + context_->set_ssl_config_service(ssl_config_service_); + proxy_service_.reset(net::ProxyService::CreateDirect()); + 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; + } websocket_->InitSocketStream(socket_.get()); websocket_->set_context(context_.get()); struct addrinfo addr; @@ -209,28 +302,55 @@ class WebSocketJobTest : public PlatformTest { SocketStream* GetSocket(SocketStreamJob* job) { return job->socket_.get(); } + const std::string& sent_data() const { + DCHECK_EQ(STREAM_MOCK_SOCKET, stream_type_); + MockSocketStream* socket = + static_cast<MockSocketStream*>(socket_.get()); + DCHECK(socket); + return socket->sent_data(); + } + const std::string& received_data() const { + DCHECK_NE(STREAM_INVALID, stream_type_); + MockSocketStreamDelegate* delegate = + static_cast<MockSocketStreamDelegate*>(websocket_->delegate_); + DCHECK(delegate); + return delegate->received_data(); + } + void TestSimpleHandshake(); void TestSlowHandshake(); void TestHandshakeWithCookie(); void TestHandshakeWithCookieButNotAllowed(); void TestHSTSUpgrade(); void TestInvalidSendData(); + void TestConnectByWebSocket(); + StreamType stream_type_; scoped_refptr<MockCookieStore> cookie_store_; scoped_refptr<MockURLRequestContext> context_; scoped_refptr<WebSocketJob> websocket_; - scoped_refptr<MockSocketStream> socket_; + scoped_refptr<SocketStream> socket_; + scoped_ptr<MockClientSocketFactory> socket_factory_; + scoped_refptr<OrderedSocketData> data_; + TestCompletionCallback sync_callback_; + scoped_refptr<MockSSLConfigService> ssl_config_service_; + scoped_ptr<net::ProxyService> proxy_service_; + scoped_ptr<net::MockHostResolver> host_resolver_; static const char kHandshakeRequestWithoutCookie[]; static const char kHandshakeRequestWithCookie[]; static const char kHandshakeRequestWithFilteredCookie[]; static const char kHandshakeResponseWithoutCookie[]; static const char kHandshakeResponseWithCookie[]; + static const char kDataHello[]; + static const char kDataWorld[]; static const size_t kHandshakeRequestWithoutCookieLength; static const size_t kHandshakeRequestWithCookieLength; static const size_t kHandshakeRequestWithFilteredCookieLength; static const size_t kHandshakeResponseWithoutCookieLength; static const size_t kHandshakeResponseWithCookieLength; + static const size_t kDataHelloLength; + static const size_t kDataWorldLength; }; const char WebSocketJobTest::kHandshakeRequestWithoutCookie[] = @@ -292,6 +412,10 @@ const char WebSocketJobTest::kHandshakeResponseWithCookie[] = "\r\n" "8jKS'y:G*Co,Wxa-"; +const char WebSocketJobTest::kDataHello[] = "Hello, "; + +const char WebSocketJobTest::kDataWorld[] = "World!\n"; + const size_t WebSocketJobTest::kHandshakeRequestWithoutCookieLength = arraysize(kHandshakeRequestWithoutCookie) - 1; const size_t WebSocketJobTest::kHandshakeRequestWithCookieLength = @@ -302,18 +426,20 @@ const size_t WebSocketJobTest::kHandshakeResponseWithoutCookieLength = arraysize(kHandshakeResponseWithoutCookie) - 1; const size_t WebSocketJobTest::kHandshakeResponseWithCookieLength = arraysize(kHandshakeResponseWithCookie) - 1; +const size_t WebSocketJobTest::kDataHelloLength = + arraysize(kDataHello) - 1; +const size_t WebSocketJobTest::kDataWorldLength = + arraysize(kDataWorld) - 1; void WebSocketJobTest::TestSimpleHandshake() { GURL url("ws://example.com/demo"); MockSocketStreamDelegate delegate; - InitWebSocketJob(url, &delegate); + InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET); SkipToConnecting(); - bool sent = websocket_->SendData(kHandshakeRequestWithoutCookie, - kHandshakeRequestWithoutCookieLength); - EXPECT_TRUE(sent); + DoSendRequest(); MessageLoop::current()->RunAllPending(); - EXPECT_EQ(kHandshakeRequestWithoutCookie, socket_->sent_data()); + EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data()); EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState()); websocket_->OnSentData(socket_.get(), kHandshakeRequestWithoutCookieLength); @@ -331,16 +457,14 @@ void WebSocketJobTest::TestSimpleHandshake() { void WebSocketJobTest::TestSlowHandshake() { GURL url("ws://example.com/demo"); MockSocketStreamDelegate delegate; - InitWebSocketJob(url, &delegate); + InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET); SkipToConnecting(); - bool sent = websocket_->SendData(kHandshakeRequestWithoutCookie, - kHandshakeRequestWithoutCookieLength); - EXPECT_TRUE(sent); + DoSendRequest(); // We assume request is sent in one data chunk (from WebKit) // We don't support streaming request. MessageLoop::current()->RunAllPending(); - EXPECT_EQ(kHandshakeRequestWithoutCookie, socket_->sent_data()); + EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data()); EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState()); websocket_->OnSentData(socket_.get(), kHandshakeRequestWithoutCookieLength); @@ -379,14 +503,14 @@ void WebSocketJobTest::TestHandshakeWithCookie() { cookieUrl, "CR-test-httponly=1", cookie_options); MockSocketStreamDelegate delegate; - InitWebSocketJob(url, &delegate); + InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET); SkipToConnecting(); bool sent = websocket_->SendData(kHandshakeRequestWithCookie, kHandshakeRequestWithCookieLength); EXPECT_TRUE(sent); MessageLoop::current()->RunAllPending(); - EXPECT_EQ(kHandshakeRequestWithFilteredCookie, socket_->sent_data()); + EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data()); EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState()); websocket_->OnSentData(socket_, kHandshakeRequestWithFilteredCookieLength); @@ -423,14 +547,14 @@ void WebSocketJobTest::TestHandshakeWithCookieButNotAllowed() { MockSocketStreamDelegate delegate; delegate.set_allow_all_cookies(false); - InitWebSocketJob(url, &delegate); + InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET); SkipToConnecting(); bool sent = websocket_->SendData(kHandshakeRequestWithCookie, kHandshakeRequestWithCookieLength); EXPECT_TRUE(sent); MessageLoop::current()->RunAllPending(); - EXPECT_EQ(kHandshakeRequestWithoutCookie, socket_->sent_data()); + EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data()); EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState()); websocket_->OnSentData(socket_, kHandshakeRequestWithoutCookieLength); EXPECT_EQ(kHandshakeRequestWithCookieLength, @@ -473,29 +597,81 @@ void WebSocketJobTest::TestHSTSUpgrade() { void WebSocketJobTest::TestInvalidSendData() { GURL url("ws://example.com/demo"); MockSocketStreamDelegate delegate; - InitWebSocketJob(url, &delegate); + InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET); SkipToConnecting(); - bool sent = websocket_->SendData(kHandshakeRequestWithoutCookie, - kHandshakeRequestWithoutCookieLength); - EXPECT_TRUE(sent); + DoSendRequest(); // We assume request is sent in one data chunk (from WebKit) // We don't support streaming request. MessageLoop::current()->RunAllPending(); - EXPECT_EQ(kHandshakeRequestWithoutCookie, socket_->sent_data()); + EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data()); EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState()); websocket_->OnSentData(socket_.get(), kHandshakeRequestWithoutCookieLength); EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent()); // We could not send any data until connection is established. - sent = websocket_->SendData(kHandshakeRequestWithoutCookie, - kHandshakeRequestWithoutCookieLength); + bool sent = websocket_->SendData(kHandshakeRequestWithoutCookie, + kHandshakeRequestWithoutCookieLength); EXPECT_FALSE(sent); EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState()); CloseWebSocketJob(); } +// Following tests verify cooperation between WebSocketJob and SocketStream. +// Other former tests use MockSocketStream as SocketStream, so we could not +// check SocketStream behavior. +// 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 + // SocketStream in basic situation. + MockWrite writes[] = { + MockWrite(true, + kHandshakeRequestWithoutCookie, + kHandshakeRequestWithoutCookieLength, + 1), + MockWrite(true, + kDataHello, + kDataHelloLength, + 3) + }; + MockRead reads[] = { + MockRead(true, + kHandshakeResponseWithoutCookie, + kHandshakeResponseWithoutCookieLength, + 2), + MockRead(true, + kDataWorld, + kDataWorldLength, + 4), + MockRead(false, 0, 5) // EOF + }; + data_ = (new OrderedSocketData( + reads, arraysize(reads), writes, arraysize(writes))); + + 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_SOCKET); + + 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); TestSimpleHandshake(); @@ -556,4 +732,14 @@ TEST_F(WebSocketJobTest, InvalidSendDataSpdyEnabled) { TestInvalidSendData(); } +TEST_F(WebSocketJobTest, ConnectByWebSocket) { + WebSocketJob::set_websocket_over_spdy_enabled(false); + TestConnectByWebSocket(); +} + +TEST_F(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) { + WebSocketJob::set_websocket_over_spdy_enabled(true); + TestConnectByWebSocket(); +} + } // namespace net |