Remove implicit conversions from scoped_refptr to T* in net/websockets/
[chromium-blink-merge.git] / net / websockets / websocket_job_test.cc
blob59d529ae13fb513b2c0fba086c37c10fb8c6fa63
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/websockets/websocket_job.h"
7 #include <string>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/callback.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h"
16 #include "net/base/completion_callback.h"
17 #include "net/base/net_errors.h"
18 #include "net/base/test_completion_callback.h"
19 #include "net/cookies/cookie_store.h"
20 #include "net/cookies/cookie_store_test_helpers.h"
21 #include "net/dns/mock_host_resolver.h"
22 #include "net/http/http_transaction_factory.h"
23 #include "net/http/transport_security_state.h"
24 #include "net/proxy/proxy_service.h"
25 #include "net/socket/next_proto.h"
26 #include "net/socket/socket_test_util.h"
27 #include "net/socket_stream/socket_stream.h"
28 #include "net/spdy/spdy_session.h"
29 #include "net/spdy/spdy_websocket_test_util.h"
30 #include "net/ssl/ssl_config_service.h"
31 #include "net/url_request/url_request_context.h"
32 #include "net/websockets/websocket_throttle.h"
33 #include "testing/gmock/include/gmock/gmock.h"
34 #include "testing/gtest/include/gtest/gtest.h"
35 #include "testing/platform_test.h"
36 #include "url/gurl.h"
38 namespace net {
40 namespace {
42 class MockSocketStream : public SocketStream {
43 public:
44 MockSocketStream(const GURL& url, SocketStream::Delegate* delegate,
45 URLRequestContext* context, CookieStore* cookie_store)
46 : SocketStream(url, delegate, context, cookie_store) {}
48 virtual void Connect() OVERRIDE {}
49 virtual bool SendData(const char* data, int len) OVERRIDE {
50 sent_data_ += std::string(data, len);
51 return true;
54 virtual void Close() OVERRIDE {}
55 virtual void RestartWithAuth(
56 const AuthCredentials& credentials) OVERRIDE {
59 virtual void DetachDelegate() OVERRIDE {
60 delegate_ = NULL;
63 const std::string& sent_data() const {
64 return sent_data_;
67 protected:
68 virtual ~MockSocketStream() {}
70 private:
71 std::string sent_data_;
74 class MockSocketStreamDelegate : public SocketStream::Delegate {
75 public:
76 MockSocketStreamDelegate()
77 : amount_sent_(0), allow_all_cookies_(true) {}
78 void set_allow_all_cookies(bool allow_all_cookies) {
79 allow_all_cookies_ = allow_all_cookies;
81 virtual ~MockSocketStreamDelegate() {}
83 void SetOnStartOpenConnection(const base::Closure& callback) {
84 on_start_open_connection_ = callback;
86 void SetOnConnected(const base::Closure& callback) {
87 on_connected_ = callback;
89 void SetOnSentData(const base::Closure& callback) {
90 on_sent_data_ = callback;
92 void SetOnReceivedData(const base::Closure& callback) {
93 on_received_data_ = callback;
95 void SetOnClose(const base::Closure& callback) {
96 on_close_ = callback;
99 virtual int OnStartOpenConnection(
100 SocketStream* socket,
101 const CompletionCallback& callback) OVERRIDE {
102 if (!on_start_open_connection_.is_null())
103 on_start_open_connection_.Run();
104 return OK;
106 virtual void OnConnected(SocketStream* socket,
107 int max_pending_send_allowed) OVERRIDE {
108 if (!on_connected_.is_null())
109 on_connected_.Run();
111 virtual void OnSentData(SocketStream* socket,
112 int amount_sent) OVERRIDE {
113 amount_sent_ += amount_sent;
114 if (!on_sent_data_.is_null())
115 on_sent_data_.Run();
117 virtual void OnReceivedData(SocketStream* socket,
118 const char* data, int len) OVERRIDE {
119 received_data_ += std::string(data, len);
120 if (!on_received_data_.is_null())
121 on_received_data_.Run();
123 virtual void OnClose(SocketStream* socket) OVERRIDE {
124 if (!on_close_.is_null())
125 on_close_.Run();
127 virtual bool CanGetCookies(SocketStream* socket,
128 const GURL& url) OVERRIDE {
129 return allow_all_cookies_;
131 virtual bool CanSetCookie(SocketStream* request,
132 const GURL& url,
133 const std::string& cookie_line,
134 CookieOptions* options) OVERRIDE {
135 return allow_all_cookies_;
138 size_t amount_sent() const { return amount_sent_; }
139 const std::string& received_data() const { return received_data_; }
141 private:
142 int amount_sent_;
143 bool allow_all_cookies_;
144 std::string received_data_;
145 base::Closure on_start_open_connection_;
146 base::Closure on_connected_;
147 base::Closure on_sent_data_;
148 base::Closure on_received_data_;
149 base::Closure on_close_;
152 class MockCookieStore : public CookieStore {
153 public:
154 struct Entry {
155 GURL url;
156 std::string cookie_line;
157 CookieOptions options;
160 MockCookieStore() {}
162 bool SetCookieWithOptions(const GURL& url,
163 const std::string& cookie_line,
164 const CookieOptions& options) {
165 Entry entry;
166 entry.url = url;
167 entry.cookie_line = cookie_line;
168 entry.options = options;
169 entries_.push_back(entry);
170 return true;
173 std::string GetCookiesWithOptions(const GURL& url,
174 const CookieOptions& options) {
175 std::string result;
176 for (size_t i = 0; i < entries_.size(); i++) {
177 Entry& entry = entries_[i];
178 if (url == entry.url) {
179 if (!result.empty()) {
180 result += "; ";
182 result += entry.cookie_line;
185 return result;
188 // CookieStore:
189 virtual void SetCookieWithOptionsAsync(
190 const GURL& url,
191 const std::string& cookie_line,
192 const CookieOptions& options,
193 const SetCookiesCallback& callback) OVERRIDE {
194 bool result = SetCookieWithOptions(url, cookie_line, options);
195 if (!callback.is_null())
196 callback.Run(result);
199 virtual void GetCookiesWithOptionsAsync(
200 const GURL& url,
201 const CookieOptions& options,
202 const GetCookiesCallback& callback) OVERRIDE {
203 if (!callback.is_null())
204 callback.Run(GetCookiesWithOptions(url, options));
207 virtual void GetAllCookiesForURLAsync(
208 const GURL& url,
209 const GetCookieListCallback& callback) OVERRIDE {
210 ADD_FAILURE();
213 virtual void DeleteCookieAsync(const GURL& url,
214 const std::string& cookie_name,
215 const base::Closure& callback) OVERRIDE {
216 ADD_FAILURE();
219 virtual void DeleteAllCreatedBetweenAsync(
220 const base::Time& delete_begin,
221 const base::Time& delete_end,
222 const DeleteCallback& callback) OVERRIDE {
223 ADD_FAILURE();
226 virtual void DeleteAllCreatedBetweenForHostAsync(
227 const base::Time delete_begin,
228 const base::Time delete_end,
229 const GURL& url,
230 const DeleteCallback& callback) OVERRIDE {
231 ADD_FAILURE();
234 virtual void DeleteSessionCookiesAsync(const DeleteCallback&) OVERRIDE {
235 ADD_FAILURE();
238 virtual CookieMonster* GetCookieMonster() OVERRIDE { return NULL; }
240 const std::vector<Entry>& entries() const { return entries_; }
242 private:
243 friend class base::RefCountedThreadSafe<MockCookieStore>;
244 virtual ~MockCookieStore() {}
246 std::vector<Entry> entries_;
249 class MockSSLConfigService : public SSLConfigService {
250 public:
251 virtual void GetSSLConfig(SSLConfig* config) OVERRIDE {}
253 protected:
254 virtual ~MockSSLConfigService() {}
257 class MockURLRequestContext : public URLRequestContext {
258 public:
259 explicit MockURLRequestContext(CookieStore* cookie_store)
260 : transport_security_state_() {
261 set_cookie_store(cookie_store);
262 set_transport_security_state(&transport_security_state_);
263 base::Time expiry = base::Time::Now() + base::TimeDelta::FromDays(1000);
264 bool include_subdomains = false;
265 transport_security_state_.AddHSTS("upgrademe.com", expiry,
266 include_subdomains);
269 virtual ~MockURLRequestContext() {
270 AssertNoURLRequests();
273 private:
274 TransportSecurityState transport_security_state_;
277 class MockHttpTransactionFactory : public HttpTransactionFactory {
278 public:
279 MockHttpTransactionFactory(NextProto next_proto,
280 OrderedSocketData* data,
281 bool enable_websocket_over_spdy) {
282 data_ = data;
283 MockConnect connect_data(SYNCHRONOUS, OK);
284 data_->set_connect_data(connect_data);
285 session_deps_.reset(new SpdySessionDependencies(next_proto));
286 session_deps_->enable_websocket_over_spdy = enable_websocket_over_spdy;
287 session_deps_->socket_factory->AddSocketDataProvider(data_);
288 http_session_ =
289 SpdySessionDependencies::SpdyCreateSession(session_deps_.get());
290 host_port_pair_.set_host("example.com");
291 host_port_pair_.set_port(80);
292 spdy_session_key_ = SpdySessionKey(host_port_pair_,
293 ProxyServer::Direct(),
294 PRIVACY_MODE_DISABLED);
295 session_ = CreateInsecureSpdySession(
296 http_session_, spdy_session_key_, BoundNetLog());
299 virtual int CreateTransaction(
300 RequestPriority priority,
301 scoped_ptr<HttpTransaction>* trans) OVERRIDE {
302 NOTREACHED();
303 return ERR_UNEXPECTED;
306 virtual HttpCache* GetCache() OVERRIDE {
307 NOTREACHED();
308 return NULL;
311 virtual HttpNetworkSession* GetSession() OVERRIDE {
312 return http_session_.get();
315 private:
316 OrderedSocketData* data_;
317 scoped_ptr<SpdySessionDependencies> session_deps_;
318 scoped_refptr<HttpNetworkSession> http_session_;
319 base::WeakPtr<SpdySession> session_;
320 HostPortPair host_port_pair_;
321 SpdySessionKey spdy_session_key_;
324 class DeletingSocketStreamDelegate : public SocketStream::Delegate {
325 public:
326 DeletingSocketStreamDelegate()
327 : delete_next_(false) {}
329 // Since this class needs to be able to delete |job_|, it must be the only
330 // reference holder (except for temporary references). Provide access to the
331 // pointer for tests to use.
332 WebSocketJob* job() { return job_.get(); }
334 void set_job(WebSocketJob* job) { job_ = job; }
336 // After calling this, the next call to a method on this delegate will delete
337 // the WebSocketJob object.
338 void set_delete_next(bool delete_next) { delete_next_ = delete_next; }
340 void DeleteJobMaybe() {
341 if (delete_next_) {
342 job_->DetachContext();
343 job_->DetachDelegate();
344 job_ = NULL;
348 // SocketStream::Delegate implementation
350 // OnStartOpenConnection() is not implemented by SocketStreamDispatcherHost
352 virtual void OnConnected(SocketStream* socket,
353 int max_pending_send_allowed) OVERRIDE {
354 DeleteJobMaybe();
357 virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE {
358 DeleteJobMaybe();
361 virtual void OnReceivedData(SocketStream* socket,
362 const char* data,
363 int len) OVERRIDE {
364 DeleteJobMaybe();
367 virtual void OnClose(SocketStream* socket) OVERRIDE { DeleteJobMaybe(); }
369 virtual void OnAuthRequired(SocketStream* socket,
370 AuthChallengeInfo* auth_info) OVERRIDE {
371 DeleteJobMaybe();
374 virtual void OnSSLCertificateError(SocketStream* socket,
375 const SSLInfo& ssl_info,
376 bool fatal) OVERRIDE {
377 DeleteJobMaybe();
380 virtual void OnError(const SocketStream* socket, int error) OVERRIDE {
381 DeleteJobMaybe();
384 // CanGetCookies() and CanSetCookies() do not appear to be able to delete the
385 // WebSocketJob object.
387 private:
388 scoped_refptr<WebSocketJob> job_;
389 bool delete_next_;
392 } // namespace
394 class WebSocketJobTest : public PlatformTest,
395 public ::testing::WithParamInterface<NextProto> {
396 public:
397 WebSocketJobTest()
398 : spdy_util_(GetParam()),
399 enable_websocket_over_spdy_(false) {}
401 virtual void SetUp() OVERRIDE {
402 stream_type_ = STREAM_INVALID;
403 cookie_store_ = new MockCookieStore;
404 context_.reset(new MockURLRequestContext(cookie_store_.get()));
406 virtual void TearDown() OVERRIDE {
407 cookie_store_ = NULL;
408 context_.reset();
409 websocket_ = NULL;
410 socket_ = NULL;
412 void DoSendRequest() {
413 EXPECT_TRUE(websocket_->SendData(kHandshakeRequestWithoutCookie,
414 kHandshakeRequestWithoutCookieLength));
416 void DoSendData() {
417 if (received_data().size() == kHandshakeResponseWithoutCookieLength)
418 websocket_->SendData(kDataHello, kDataHelloLength);
420 void DoSync() {
421 sync_test_callback_.callback().Run(OK);
423 int WaitForResult() {
424 return sync_test_callback_.WaitForResult();
427 protected:
428 enum StreamType {
429 STREAM_INVALID,
430 STREAM_MOCK_SOCKET,
431 STREAM_SOCKET,
432 STREAM_SPDY_WEBSOCKET,
434 enum ThrottlingOption {
435 THROTTLING_OFF,
436 THROTTLING_ON,
438 enum SpdyOption {
439 SPDY_OFF,
440 SPDY_ON,
442 void InitWebSocketJob(const GURL& url,
443 MockSocketStreamDelegate* delegate,
444 StreamType stream_type) {
445 DCHECK_NE(STREAM_INVALID, stream_type);
446 stream_type_ = stream_type;
447 websocket_ = new WebSocketJob(delegate);
449 if (stream_type == STREAM_MOCK_SOCKET)
450 socket_ = new MockSocketStream(url, websocket_.get(), context_.get(),
451 NULL);
453 if (stream_type == STREAM_SOCKET || stream_type == STREAM_SPDY_WEBSOCKET) {
454 if (stream_type == STREAM_SPDY_WEBSOCKET) {
455 http_factory_.reset(new MockHttpTransactionFactory(
456 GetParam(), data_.get(), enable_websocket_over_spdy_));
457 context_->set_http_transaction_factory(http_factory_.get());
460 ssl_config_service_ = new MockSSLConfigService();
461 context_->set_ssl_config_service(ssl_config_service_.get());
462 proxy_service_.reset(ProxyService::CreateDirect());
463 context_->set_proxy_service(proxy_service_.get());
464 host_resolver_.reset(new MockHostResolver);
465 context_->set_host_resolver(host_resolver_.get());
467 socket_ = new SocketStream(url, websocket_.get(), context_.get(), NULL);
468 socket_factory_.reset(new MockClientSocketFactory);
469 DCHECK(data_.get());
470 socket_factory_->AddSocketDataProvider(data_.get());
471 socket_->SetClientSocketFactory(socket_factory_.get());
474 websocket_->InitSocketStream(socket_.get());
475 // MockHostResolver resolves all hosts to 127.0.0.1; however, when we create
476 // a WebSocketJob purely to block another one in a throttling test, we don't
477 // perform a real connect. In that case, the following address is used
478 // instead.
479 IPAddressNumber ip;
480 ParseIPLiteralToNumber("127.0.0.1", &ip);
481 websocket_->addresses_ = AddressList::CreateFromIPAddress(ip, 80);
483 void SkipToConnecting() {
484 websocket_->state_ = WebSocketJob::CONNECTING;
485 ASSERT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(websocket_.get()));
487 WebSocketJob::State GetWebSocketJobState() {
488 return websocket_->state_;
490 void CloseWebSocketJob() {
491 if (websocket_->socket_.get()) {
492 websocket_->socket_->DetachDelegate();
493 WebSocketThrottle::GetInstance()->RemoveFromQueue(websocket_.get());
495 websocket_->state_ = WebSocketJob::CLOSED;
496 websocket_->delegate_ = NULL;
497 websocket_->socket_ = NULL;
499 SocketStream* GetSocket(SocketStreamJob* job) {
500 return job->socket_.get();
502 const std::string& sent_data() const {
503 DCHECK_EQ(STREAM_MOCK_SOCKET, stream_type_);
504 MockSocketStream* socket =
505 static_cast<MockSocketStream*>(socket_.get());
506 DCHECK(socket);
507 return socket->sent_data();
509 const std::string& received_data() const {
510 DCHECK_NE(STREAM_INVALID, stream_type_);
511 MockSocketStreamDelegate* delegate =
512 static_cast<MockSocketStreamDelegate*>(websocket_->delegate_);
513 DCHECK(delegate);
514 return delegate->received_data();
517 void TestSimpleHandshake();
518 void TestSlowHandshake();
519 void TestHandshakeWithCookie();
520 void TestHandshakeWithCookieButNotAllowed();
521 void TestHSTSUpgrade();
522 void TestInvalidSendData();
523 void TestConnectByWebSocket(ThrottlingOption throttling);
524 void TestConnectBySpdy(SpdyOption spdy, ThrottlingOption throttling);
525 void TestThrottlingLimit();
527 SpdyWebSocketTestUtil spdy_util_;
528 StreamType stream_type_;
529 scoped_refptr<MockCookieStore> cookie_store_;
530 scoped_ptr<MockURLRequestContext> context_;
531 scoped_refptr<WebSocketJob> websocket_;
532 scoped_refptr<SocketStream> socket_;
533 scoped_ptr<MockClientSocketFactory> socket_factory_;
534 scoped_ptr<OrderedSocketData> data_;
535 TestCompletionCallback sync_test_callback_;
536 scoped_refptr<MockSSLConfigService> ssl_config_service_;
537 scoped_ptr<ProxyService> proxy_service_;
538 scoped_ptr<MockHostResolver> host_resolver_;
539 scoped_ptr<MockHttpTransactionFactory> http_factory_;
541 // Must be set before call to enable_websocket_over_spdy, defaults to false.
542 bool enable_websocket_over_spdy_;
544 static const char kHandshakeRequestWithoutCookie[];
545 static const char kHandshakeRequestWithCookie[];
546 static const char kHandshakeRequestWithFilteredCookie[];
547 static const char kHandshakeResponseWithoutCookie[];
548 static const char kHandshakeResponseWithCookie[];
549 static const char kDataHello[];
550 static const char kDataWorld[];
551 static const char* const kHandshakeRequestForSpdy[];
552 static const char* const kHandshakeResponseForSpdy[];
553 static const size_t kHandshakeRequestWithoutCookieLength;
554 static const size_t kHandshakeRequestWithCookieLength;
555 static const size_t kHandshakeRequestWithFilteredCookieLength;
556 static const size_t kHandshakeResponseWithoutCookieLength;
557 static const size_t kHandshakeResponseWithCookieLength;
558 static const size_t kDataHelloLength;
559 static const size_t kDataWorldLength;
562 // Tests using this fixture verify that the WebSocketJob can handle being
563 // deleted while calling back to the delegate correctly. These tests need to be
564 // run under AddressSanitizer or other systems for detecting use-after-free
565 // errors in order to find problems.
566 class WebSocketJobDeleteTest : public ::testing::Test {
567 protected:
568 WebSocketJobDeleteTest()
569 : delegate_(new DeletingSocketStreamDelegate),
570 cookie_store_(new MockCookieStore),
571 context_(new MockURLRequestContext(cookie_store_.get())) {
572 WebSocketJob* websocket = new WebSocketJob(delegate_.get());
573 delegate_->set_job(websocket);
575 socket_ = new MockSocketStream(
576 GURL("ws://127.0.0.1/"), websocket, context_.get(), NULL);
578 websocket->InitSocketStream(socket_.get());
581 void SetDeleteNext() { return delegate_->set_delete_next(true); }
582 WebSocketJob* job() { return delegate_->job(); }
584 scoped_ptr<DeletingSocketStreamDelegate> delegate_;
585 scoped_refptr<MockCookieStore> cookie_store_;
586 scoped_ptr<MockURLRequestContext> context_;
587 scoped_refptr<SocketStream> socket_;
590 const char WebSocketJobTest::kHandshakeRequestWithoutCookie[] =
591 "GET /demo HTTP/1.1\r\n"
592 "Host: example.com\r\n"
593 "Upgrade: WebSocket\r\n"
594 "Connection: Upgrade\r\n"
595 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
596 "Origin: http://example.com\r\n"
597 "Sec-WebSocket-Protocol: sample\r\n"
598 "Sec-WebSocket-Version: 13\r\n"
599 "\r\n";
601 const char WebSocketJobTest::kHandshakeRequestWithCookie[] =
602 "GET /demo HTTP/1.1\r\n"
603 "Host: example.com\r\n"
604 "Upgrade: WebSocket\r\n"
605 "Connection: Upgrade\r\n"
606 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
607 "Origin: http://example.com\r\n"
608 "Sec-WebSocket-Protocol: sample\r\n"
609 "Sec-WebSocket-Version: 13\r\n"
610 "Cookie: WK-test=1\r\n"
611 "\r\n";
613 const char WebSocketJobTest::kHandshakeRequestWithFilteredCookie[] =
614 "GET /demo HTTP/1.1\r\n"
615 "Host: example.com\r\n"
616 "Upgrade: WebSocket\r\n"
617 "Connection: Upgrade\r\n"
618 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
619 "Origin: http://example.com\r\n"
620 "Sec-WebSocket-Protocol: sample\r\n"
621 "Sec-WebSocket-Version: 13\r\n"
622 "Cookie: CR-test=1; CR-test-httponly=1\r\n"
623 "\r\n";
625 const char WebSocketJobTest::kHandshakeResponseWithoutCookie[] =
626 "HTTP/1.1 101 Switching Protocols\r\n"
627 "Upgrade: websocket\r\n"
628 "Connection: Upgrade\r\n"
629 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
630 "Sec-WebSocket-Protocol: sample\r\n"
631 "\r\n";
633 const char WebSocketJobTest::kHandshakeResponseWithCookie[] =
634 "HTTP/1.1 101 Switching Protocols\r\n"
635 "Upgrade: websocket\r\n"
636 "Connection: Upgrade\r\n"
637 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
638 "Sec-WebSocket-Protocol: sample\r\n"
639 "Set-Cookie: CR-set-test=1\r\n"
640 "\r\n";
642 const char WebSocketJobTest::kDataHello[] = "Hello, ";
644 const char WebSocketJobTest::kDataWorld[] = "World!\n";
646 const size_t WebSocketJobTest::kHandshakeRequestWithoutCookieLength =
647 arraysize(kHandshakeRequestWithoutCookie) - 1;
648 const size_t WebSocketJobTest::kHandshakeRequestWithCookieLength =
649 arraysize(kHandshakeRequestWithCookie) - 1;
650 const size_t WebSocketJobTest::kHandshakeRequestWithFilteredCookieLength =
651 arraysize(kHandshakeRequestWithFilteredCookie) - 1;
652 const size_t WebSocketJobTest::kHandshakeResponseWithoutCookieLength =
653 arraysize(kHandshakeResponseWithoutCookie) - 1;
654 const size_t WebSocketJobTest::kHandshakeResponseWithCookieLength =
655 arraysize(kHandshakeResponseWithCookie) - 1;
656 const size_t WebSocketJobTest::kDataHelloLength =
657 arraysize(kDataHello) - 1;
658 const size_t WebSocketJobTest::kDataWorldLength =
659 arraysize(kDataWorld) - 1;
661 void WebSocketJobTest::TestSimpleHandshake() {
662 GURL url("ws://example.com/demo");
663 MockSocketStreamDelegate delegate;
664 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
665 SkipToConnecting();
667 DoSendRequest();
668 base::MessageLoop::current()->RunUntilIdle();
669 EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
670 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
671 websocket_->OnSentData(socket_.get(),
672 kHandshakeRequestWithoutCookieLength);
673 EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
675 websocket_->OnReceivedData(socket_.get(),
676 kHandshakeResponseWithoutCookie,
677 kHandshakeResponseWithoutCookieLength);
678 base::MessageLoop::current()->RunUntilIdle();
679 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
680 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
681 CloseWebSocketJob();
684 void WebSocketJobTest::TestSlowHandshake() {
685 GURL url("ws://example.com/demo");
686 MockSocketStreamDelegate delegate;
687 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
688 SkipToConnecting();
690 DoSendRequest();
691 // We assume request is sent in one data chunk (from WebKit)
692 // We don't support streaming request.
693 base::MessageLoop::current()->RunUntilIdle();
694 EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
695 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
696 websocket_->OnSentData(socket_.get(),
697 kHandshakeRequestWithoutCookieLength);
698 EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
700 std::vector<std::string> lines;
701 base::SplitString(kHandshakeResponseWithoutCookie, '\n', &lines);
702 for (size_t i = 0; i < lines.size() - 2; i++) {
703 std::string line = lines[i] + "\r\n";
704 SCOPED_TRACE("Line: " + line);
705 websocket_->OnReceivedData(socket_.get(), line.c_str(), line.size());
706 base::MessageLoop::current()->RunUntilIdle();
707 EXPECT_TRUE(delegate.received_data().empty());
708 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
710 websocket_->OnReceivedData(socket_.get(), "\r\n", 2);
711 base::MessageLoop::current()->RunUntilIdle();
712 EXPECT_FALSE(delegate.received_data().empty());
713 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
714 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
715 CloseWebSocketJob();
718 INSTANTIATE_TEST_CASE_P(
719 NextProto,
720 WebSocketJobTest,
721 testing::Values(kProtoDeprecatedSPDY2,
722 kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
724 TEST_P(WebSocketJobTest, DelayedCookies) {
725 enable_websocket_over_spdy_ = true;
726 GURL url("ws://example.com/demo");
727 GURL cookieUrl("http://example.com/demo");
728 CookieOptions cookie_options;
729 scoped_refptr<DelayedCookieMonster> cookie_store = new DelayedCookieMonster();
730 context_->set_cookie_store(cookie_store.get());
731 cookie_store->SetCookieWithOptionsAsync(cookieUrl,
732 "CR-test=1",
733 cookie_options,
734 CookieMonster::SetCookiesCallback());
735 cookie_options.set_include_httponly();
736 cookie_store->SetCookieWithOptionsAsync(
737 cookieUrl, "CR-test-httponly=1", cookie_options,
738 CookieMonster::SetCookiesCallback());
740 MockSocketStreamDelegate delegate;
741 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
742 SkipToConnecting();
744 bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
745 kHandshakeRequestWithCookieLength);
746 EXPECT_TRUE(sent);
747 base::MessageLoop::current()->RunUntilIdle();
748 EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
749 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
750 websocket_->OnSentData(socket_.get(),
751 kHandshakeRequestWithFilteredCookieLength);
752 EXPECT_EQ(kHandshakeRequestWithCookieLength,
753 delegate.amount_sent());
755 websocket_->OnReceivedData(socket_.get(),
756 kHandshakeResponseWithCookie,
757 kHandshakeResponseWithCookieLength);
758 base::MessageLoop::current()->RunUntilIdle();
759 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
760 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
762 CloseWebSocketJob();
765 void WebSocketJobTest::TestHandshakeWithCookie() {
766 GURL url("ws://example.com/demo");
767 GURL cookieUrl("http://example.com/demo");
768 CookieOptions cookie_options;
769 cookie_store_->SetCookieWithOptions(
770 cookieUrl, "CR-test=1", cookie_options);
771 cookie_options.set_include_httponly();
772 cookie_store_->SetCookieWithOptions(
773 cookieUrl, "CR-test-httponly=1", cookie_options);
775 MockSocketStreamDelegate delegate;
776 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
777 SkipToConnecting();
779 bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
780 kHandshakeRequestWithCookieLength);
781 EXPECT_TRUE(sent);
782 base::MessageLoop::current()->RunUntilIdle();
783 EXPECT_EQ(kHandshakeRequestWithFilteredCookie, sent_data());
784 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
785 websocket_->OnSentData(socket_.get(),
786 kHandshakeRequestWithFilteredCookieLength);
787 EXPECT_EQ(kHandshakeRequestWithCookieLength,
788 delegate.amount_sent());
790 websocket_->OnReceivedData(socket_.get(),
791 kHandshakeResponseWithCookie,
792 kHandshakeResponseWithCookieLength);
793 base::MessageLoop::current()->RunUntilIdle();
794 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
795 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
797 EXPECT_EQ(3U, cookie_store_->entries().size());
798 EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
799 EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
800 EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
801 EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
802 EXPECT_EQ(cookieUrl, cookie_store_->entries()[2].url);
803 EXPECT_EQ("CR-set-test=1", cookie_store_->entries()[2].cookie_line);
805 CloseWebSocketJob();
808 void WebSocketJobTest::TestHandshakeWithCookieButNotAllowed() {
809 GURL url("ws://example.com/demo");
810 GURL cookieUrl("http://example.com/demo");
811 CookieOptions cookie_options;
812 cookie_store_->SetCookieWithOptions(
813 cookieUrl, "CR-test=1", cookie_options);
814 cookie_options.set_include_httponly();
815 cookie_store_->SetCookieWithOptions(
816 cookieUrl, "CR-test-httponly=1", cookie_options);
818 MockSocketStreamDelegate delegate;
819 delegate.set_allow_all_cookies(false);
820 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
821 SkipToConnecting();
823 bool sent = websocket_->SendData(kHandshakeRequestWithCookie,
824 kHandshakeRequestWithCookieLength);
825 EXPECT_TRUE(sent);
826 base::MessageLoop::current()->RunUntilIdle();
827 EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
828 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
829 websocket_->OnSentData(socket_.get(), kHandshakeRequestWithoutCookieLength);
830 EXPECT_EQ(kHandshakeRequestWithCookieLength, delegate.amount_sent());
832 websocket_->OnReceivedData(socket_.get(),
833 kHandshakeResponseWithCookie,
834 kHandshakeResponseWithCookieLength);
835 base::MessageLoop::current()->RunUntilIdle();
836 EXPECT_EQ(kHandshakeResponseWithoutCookie, delegate.received_data());
837 EXPECT_EQ(WebSocketJob::OPEN, GetWebSocketJobState());
839 EXPECT_EQ(2U, cookie_store_->entries().size());
840 EXPECT_EQ(cookieUrl, cookie_store_->entries()[0].url);
841 EXPECT_EQ("CR-test=1", cookie_store_->entries()[0].cookie_line);
842 EXPECT_EQ(cookieUrl, cookie_store_->entries()[1].url);
843 EXPECT_EQ("CR-test-httponly=1", cookie_store_->entries()[1].cookie_line);
845 CloseWebSocketJob();
848 void WebSocketJobTest::TestHSTSUpgrade() {
849 GURL url("ws://upgrademe.com/");
850 MockSocketStreamDelegate delegate;
851 scoped_refptr<SocketStreamJob> job =
852 SocketStreamJob::CreateSocketStreamJob(
853 url, &delegate, context_->transport_security_state(),
854 context_->ssl_config_service(), NULL, NULL);
855 EXPECT_TRUE(GetSocket(job.get())->is_secure());
856 job->DetachDelegate();
858 url = GURL("ws://donotupgrademe.com/");
859 job = SocketStreamJob::CreateSocketStreamJob(
860 url, &delegate, context_->transport_security_state(),
861 context_->ssl_config_service(), NULL, NULL);
862 EXPECT_FALSE(GetSocket(job.get())->is_secure());
863 job->DetachDelegate();
866 void WebSocketJobTest::TestInvalidSendData() {
867 GURL url("ws://example.com/demo");
868 MockSocketStreamDelegate delegate;
869 InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
870 SkipToConnecting();
872 DoSendRequest();
873 // We assume request is sent in one data chunk (from WebKit)
874 // We don't support streaming request.
875 base::MessageLoop::current()->RunUntilIdle();
876 EXPECT_EQ(kHandshakeRequestWithoutCookie, sent_data());
877 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
878 websocket_->OnSentData(socket_.get(),
879 kHandshakeRequestWithoutCookieLength);
880 EXPECT_EQ(kHandshakeRequestWithoutCookieLength, delegate.amount_sent());
882 // We could not send any data until connection is established.
883 bool sent = websocket_->SendData(kHandshakeRequestWithoutCookie,
884 kHandshakeRequestWithoutCookieLength);
885 EXPECT_FALSE(sent);
886 EXPECT_EQ(WebSocketJob::CONNECTING, GetWebSocketJobState());
887 CloseWebSocketJob();
890 // Following tests verify cooperation between WebSocketJob and SocketStream.
891 // Other former tests use MockSocketStream as SocketStream, so we could not
892 // check SocketStream behavior.
893 // OrderedSocketData provide socket level verifiation by checking out-going
894 // packets in comparison with the MockWrite array and emulating in-coming
895 // packets with MockRead array.
897 void WebSocketJobTest::TestConnectByWebSocket(
898 ThrottlingOption throttling) {
899 // This is a test for verifying cooperation between WebSocketJob and
900 // SocketStream. If |throttling| was |THROTTLING_OFF|, it test basic
901 // situation. If |throttling| was |THROTTLING_ON|, throttling limits the
902 // latter connection.
903 MockWrite writes[] = {
904 MockWrite(ASYNC,
905 kHandshakeRequestWithoutCookie,
906 kHandshakeRequestWithoutCookieLength,
908 MockWrite(ASYNC,
909 kDataHello,
910 kDataHelloLength,
913 MockRead reads[] = {
914 MockRead(ASYNC,
915 kHandshakeResponseWithoutCookie,
916 kHandshakeResponseWithoutCookieLength,
918 MockRead(ASYNC,
919 kDataWorld,
920 kDataWorldLength,
922 MockRead(SYNCHRONOUS, 0, 5) // EOF
924 data_.reset(new OrderedSocketData(
925 reads, arraysize(reads), writes, arraysize(writes)));
927 GURL url("ws://example.com/demo");
928 MockSocketStreamDelegate delegate;
929 WebSocketJobTest* test = this;
930 if (throttling == THROTTLING_ON)
931 delegate.SetOnStartOpenConnection(
932 base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
933 delegate.SetOnConnected(
934 base::Bind(&WebSocketJobTest::DoSendRequest,
935 base::Unretained(test)));
936 delegate.SetOnReceivedData(
937 base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
938 delegate.SetOnClose(
939 base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
940 InitWebSocketJob(url, &delegate, STREAM_SOCKET);
942 scoped_refptr<WebSocketJob> block_websocket;
943 if (throttling == THROTTLING_ON) {
944 // Create former WebSocket object which obstructs the latter one.
945 block_websocket = new WebSocketJob(NULL);
946 block_websocket->addresses_ = AddressList(websocket_->address_list());
947 ASSERT_TRUE(
948 WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
951 websocket_->Connect();
953 if (throttling == THROTTLING_ON) {
954 EXPECT_EQ(OK, WaitForResult());
955 EXPECT_TRUE(websocket_->IsWaiting());
957 // Remove the former WebSocket object from throttling queue to unblock the
958 // latter.
959 block_websocket->state_ = WebSocketJob::CLOSED;
960 WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
961 block_websocket = NULL;
964 EXPECT_EQ(OK, WaitForResult());
965 EXPECT_TRUE(data_->at_read_eof());
966 EXPECT_TRUE(data_->at_write_eof());
967 EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
970 void WebSocketJobTest::TestConnectBySpdy(
971 SpdyOption spdy, ThrottlingOption throttling) {
972 // This is a test for verifying cooperation between WebSocketJob and
973 // SocketStream in the situation we have SPDY session to the server. If
974 // |throttling| was |THROTTLING_ON|, throttling limits the latter connection.
975 // If you enabled spdy, you should specify |spdy| as |SPDY_ON|. Expected
976 // results depend on its configuration.
977 MockWrite writes_websocket[] = {
978 MockWrite(ASYNC,
979 kHandshakeRequestWithoutCookie,
980 kHandshakeRequestWithoutCookieLength,
982 MockWrite(ASYNC,
983 kDataHello,
984 kDataHelloLength,
987 MockRead reads_websocket[] = {
988 MockRead(ASYNC,
989 kHandshakeResponseWithoutCookie,
990 kHandshakeResponseWithoutCookieLength,
992 MockRead(ASYNC,
993 kDataWorld,
994 kDataWorldLength,
996 MockRead(SYNCHRONOUS, 0, 5) // EOF
999 scoped_ptr<SpdyHeaderBlock> request_headers(new SpdyHeaderBlock());
1000 spdy_util_.SetHeader("path", "/demo", request_headers.get());
1001 spdy_util_.SetHeader("version", "WebSocket/13", request_headers.get());
1002 spdy_util_.SetHeader("scheme", "ws", request_headers.get());
1003 spdy_util_.SetHeader("host", "example.com", request_headers.get());
1004 spdy_util_.SetHeader("origin", "http://example.com", request_headers.get());
1005 spdy_util_.SetHeader("sec-websocket-protocol", "sample",
1006 request_headers.get());
1008 scoped_ptr<SpdyHeaderBlock> response_headers(new SpdyHeaderBlock());
1009 spdy_util_.SetHeader("status", "101 Switching Protocols",
1010 response_headers.get());
1011 spdy_util_.SetHeader("sec-websocket-protocol", "sample",
1012 response_headers.get());
1014 const SpdyStreamId kStreamId = 1;
1015 scoped_ptr<SpdyFrame> request_frame(
1016 spdy_util_.ConstructSpdyWebSocketHandshakeRequestFrame(
1017 request_headers.Pass(),
1018 kStreamId,
1019 MEDIUM));
1020 scoped_ptr<SpdyFrame> response_frame(
1021 spdy_util_.ConstructSpdyWebSocketHandshakeResponseFrame(
1022 response_headers.Pass(),
1023 kStreamId,
1024 MEDIUM));
1025 scoped_ptr<SpdyFrame> data_hello_frame(
1026 spdy_util_.ConstructSpdyWebSocketDataFrame(
1027 kDataHello,
1028 kDataHelloLength,
1029 kStreamId,
1030 false));
1031 scoped_ptr<SpdyFrame> data_world_frame(
1032 spdy_util_.ConstructSpdyWebSocketDataFrame(
1033 kDataWorld,
1034 kDataWorldLength,
1035 kStreamId,
1036 false));
1037 MockWrite writes_spdy[] = {
1038 CreateMockWrite(*request_frame.get(), 1),
1039 CreateMockWrite(*data_hello_frame.get(), 3),
1041 MockRead reads_spdy[] = {
1042 CreateMockRead(*response_frame.get(), 2),
1043 CreateMockRead(*data_world_frame.get(), 4),
1044 MockRead(SYNCHRONOUS, 0, 5) // EOF
1047 if (spdy == SPDY_ON)
1048 data_.reset(new OrderedSocketData(
1049 reads_spdy, arraysize(reads_spdy),
1050 writes_spdy, arraysize(writes_spdy)));
1051 else
1052 data_.reset(new OrderedSocketData(
1053 reads_websocket, arraysize(reads_websocket),
1054 writes_websocket, arraysize(writes_websocket)));
1056 GURL url("ws://example.com/demo");
1057 MockSocketStreamDelegate delegate;
1058 WebSocketJobTest* test = this;
1059 if (throttling == THROTTLING_ON)
1060 delegate.SetOnStartOpenConnection(
1061 base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
1062 delegate.SetOnConnected(
1063 base::Bind(&WebSocketJobTest::DoSendRequest,
1064 base::Unretained(test)));
1065 delegate.SetOnReceivedData(
1066 base::Bind(&WebSocketJobTest::DoSendData, base::Unretained(test)));
1067 delegate.SetOnClose(
1068 base::Bind(&WebSocketJobTest::DoSync, base::Unretained(test)));
1069 InitWebSocketJob(url, &delegate, STREAM_SPDY_WEBSOCKET);
1071 scoped_refptr<WebSocketJob> block_websocket;
1072 if (throttling == THROTTLING_ON) {
1073 // Create former WebSocket object which obstructs the latter one.
1074 block_websocket = new WebSocketJob(NULL);
1075 block_websocket->addresses_ = AddressList(websocket_->address_list());
1076 ASSERT_TRUE(
1077 WebSocketThrottle::GetInstance()->PutInQueue(block_websocket.get()));
1080 websocket_->Connect();
1082 if (throttling == THROTTLING_ON) {
1083 EXPECT_EQ(OK, WaitForResult());
1084 EXPECT_TRUE(websocket_->IsWaiting());
1086 // Remove the former WebSocket object from throttling queue to unblock the
1087 // latter.
1088 block_websocket->state_ = WebSocketJob::CLOSED;
1089 WebSocketThrottle::GetInstance()->RemoveFromQueue(block_websocket.get());
1090 block_websocket = NULL;
1093 EXPECT_EQ(OK, WaitForResult());
1094 EXPECT_TRUE(data_->at_read_eof());
1095 EXPECT_TRUE(data_->at_write_eof());
1096 EXPECT_EQ(WebSocketJob::CLOSED, GetWebSocketJobState());
1099 void WebSocketJobTest::TestThrottlingLimit() {
1100 std::vector<scoped_refptr<WebSocketJob> > jobs;
1101 const int kMaxWebSocketJobsThrottled = 1024;
1102 IPAddressNumber ip;
1103 ParseIPLiteralToNumber("127.0.0.1", &ip);
1104 for (int i = 0; i < kMaxWebSocketJobsThrottled + 1; ++i) {
1105 scoped_refptr<WebSocketJob> job = new WebSocketJob(NULL);
1106 job->addresses_ = AddressList(AddressList::CreateFromIPAddress(ip, 80));
1107 if (i >= kMaxWebSocketJobsThrottled)
1108 EXPECT_FALSE(WebSocketThrottle::GetInstance()->PutInQueue(job.get()));
1109 else
1110 EXPECT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(job.get()));
1111 jobs.push_back(job);
1114 // Close the jobs in reverse order. Otherwise, We need to make them prepared
1115 // for Wakeup call.
1116 for (std::vector<scoped_refptr<WebSocketJob> >::reverse_iterator iter =
1117 jobs.rbegin();
1118 iter != jobs.rend();
1119 ++iter) {
1120 WebSocketJob* job = (*iter).get();
1121 job->state_ = WebSocketJob::CLOSED;
1122 WebSocketThrottle::GetInstance()->RemoveFromQueue(job);
1126 // Execute tests in both spdy-disabled mode and spdy-enabled mode.
1127 TEST_P(WebSocketJobTest, SimpleHandshake) {
1128 TestSimpleHandshake();
1131 TEST_P(WebSocketJobTest, SlowHandshake) {
1132 TestSlowHandshake();
1135 TEST_P(WebSocketJobTest, HandshakeWithCookie) {
1136 TestHandshakeWithCookie();
1139 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
1140 TestHandshakeWithCookieButNotAllowed();
1143 TEST_P(WebSocketJobTest, HSTSUpgrade) {
1144 TestHSTSUpgrade();
1147 TEST_P(WebSocketJobTest, InvalidSendData) {
1148 TestInvalidSendData();
1151 TEST_P(WebSocketJobTest, SimpleHandshakeSpdyEnabled) {
1152 enable_websocket_over_spdy_ = true;
1153 TestSimpleHandshake();
1156 TEST_P(WebSocketJobTest, SlowHandshakeSpdyEnabled) {
1157 enable_websocket_over_spdy_ = true;
1158 TestSlowHandshake();
1161 TEST_P(WebSocketJobTest, HandshakeWithCookieSpdyEnabled) {
1162 enable_websocket_over_spdy_ = true;
1163 TestHandshakeWithCookie();
1166 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowedSpdyEnabled) {
1167 enable_websocket_over_spdy_ = true;
1168 TestHandshakeWithCookieButNotAllowed();
1171 TEST_P(WebSocketJobTest, HSTSUpgradeSpdyEnabled) {
1172 enable_websocket_over_spdy_ = true;
1173 TestHSTSUpgrade();
1176 TEST_P(WebSocketJobTest, InvalidSendDataSpdyEnabled) {
1177 enable_websocket_over_spdy_ = true;
1178 TestInvalidSendData();
1181 TEST_P(WebSocketJobTest, ConnectByWebSocket) {
1182 enable_websocket_over_spdy_ = true;
1183 TestConnectByWebSocket(THROTTLING_OFF);
1186 TEST_P(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) {
1187 enable_websocket_over_spdy_ = true;
1188 TestConnectByWebSocket(THROTTLING_OFF);
1191 TEST_P(WebSocketJobTest, ConnectBySpdy) {
1192 TestConnectBySpdy(SPDY_OFF, THROTTLING_OFF);
1195 TEST_P(WebSocketJobTest, ConnectBySpdySpdyEnabled) {
1196 enable_websocket_over_spdy_ = true;
1197 TestConnectBySpdy(SPDY_ON, THROTTLING_OFF);
1200 TEST_P(WebSocketJobTest, ThrottlingWebSocket) {
1201 TestConnectByWebSocket(THROTTLING_ON);
1204 TEST_P(WebSocketJobTest, ThrottlingMaxNumberOfThrottledJobLimit) {
1205 TestThrottlingLimit();
1208 TEST_P(WebSocketJobTest, ThrottlingWebSocketSpdyEnabled) {
1209 enable_websocket_over_spdy_ = true;
1210 TestConnectByWebSocket(THROTTLING_ON);
1213 TEST_P(WebSocketJobTest, ThrottlingSpdy) {
1214 TestConnectBySpdy(SPDY_OFF, THROTTLING_ON);
1217 TEST_P(WebSocketJobTest, ThrottlingSpdySpdyEnabled) {
1218 enable_websocket_over_spdy_ = true;
1219 TestConnectBySpdy(SPDY_ON, THROTTLING_ON);
1222 TEST_F(WebSocketJobDeleteTest, OnClose) {
1223 SetDeleteNext();
1224 job()->OnClose(socket_.get());
1225 // OnClose() sets WebSocketJob::_socket to NULL before we can detach it, so
1226 // socket_->delegate is still set at this point. Clear it to avoid hitting
1227 // DCHECK(!delegate_) in the SocketStream destructor. SocketStream::Finish()
1228 // is the only caller of this method in real code, and it also sets delegate_
1229 // to NULL.
1230 socket_->DetachDelegate();
1231 EXPECT_FALSE(job());
1234 TEST_F(WebSocketJobDeleteTest, OnAuthRequired) {
1235 SetDeleteNext();
1236 job()->OnAuthRequired(socket_.get(), NULL);
1237 EXPECT_FALSE(job());
1240 TEST_F(WebSocketJobDeleteTest, OnSSLCertificateError) {
1241 SSLInfo ssl_info;
1242 SetDeleteNext();
1243 job()->OnSSLCertificateError(socket_.get(), ssl_info, true);
1244 EXPECT_FALSE(job());
1247 TEST_F(WebSocketJobDeleteTest, OnError) {
1248 SetDeleteNext();
1249 job()->OnError(socket_.get(), ERR_CONNECTION_RESET);
1250 EXPECT_FALSE(job());
1253 TEST_F(WebSocketJobDeleteTest, OnSentSpdyHeaders) {
1254 job()->Connect();
1255 SetDeleteNext();
1256 job()->OnSentSpdyHeaders();
1257 EXPECT_FALSE(job());
1260 TEST_F(WebSocketJobDeleteTest, OnSentHandshakeRequest) {
1261 static const char kMinimalRequest[] =
1262 "GET /demo HTTP/1.1\r\n"
1263 "Host: example.com\r\n"
1264 "Upgrade: WebSocket\r\n"
1265 "Connection: Upgrade\r\n"
1266 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
1267 "Origin: http://example.com\r\n"
1268 "Sec-WebSocket-Version: 13\r\n"
1269 "\r\n";
1270 const size_t kMinimalRequestSize = arraysize(kMinimalRequest) - 1;
1271 job()->Connect();
1272 job()->SendData(kMinimalRequest, kMinimalRequestSize);
1273 SetDeleteNext();
1274 job()->OnSentData(socket_.get(), kMinimalRequestSize);
1275 EXPECT_FALSE(job());
1278 TEST_F(WebSocketJobDeleteTest, NotifyHeadersComplete) {
1279 static const char kMinimalResponse[] =
1280 "HTTP/1.1 101 Switching Protocols\r\n"
1281 "Upgrade: websocket\r\n"
1282 "Connection: Upgrade\r\n"
1283 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
1284 "\r\n";
1285 job()->Connect();
1286 SetDeleteNext();
1287 job()->OnReceivedData(
1288 socket_.get(), kMinimalResponse, arraysize(kMinimalResponse) - 1);
1289 EXPECT_FALSE(job());
1292 // TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation.
1293 // TODO(toyoshim,yutak): Add tests to verify closing handshake.
1294 } // namespace net