Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / net / websockets / websocket_job_test.cc
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.
4
5 #include "net/websockets/websocket_job.h"
6
7 #include <string>
8 #include <vector>
9
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"
37
38 namespace net {
39
40 namespace {
41
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) {}
47
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;
52   }
53
54   virtual void Close() OVERRIDE {}
55   virtual void RestartWithAuth(
56       const AuthCredentials& credentials) OVERRIDE {
57   }
58
59   virtual void DetachDelegate() OVERRIDE {
60     delegate_ = NULL;
61   }
62
63   const std::string& sent_data() const {
64     return sent_data_;
65   }
66
67  protected:
68   virtual ~MockSocketStream() {}
69
70  private:
71   std::string sent_data_;
72 };
73
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;
80   }
81   virtual ~MockSocketStreamDelegate() {}
82
83   void SetOnStartOpenConnection(const base::Closure& callback) {
84     on_start_open_connection_ = callback;
85   }
86   void SetOnConnected(const base::Closure& callback) {
87     on_connected_ = callback;
88   }
89   void SetOnSentData(const base::Closure& callback) {
90     on_sent_data_ = callback;
91   }
92   void SetOnReceivedData(const base::Closure& callback) {
93     on_received_data_ = callback;
94   }
95   void SetOnClose(const base::Closure& callback) {
96     on_close_ = callback;
97   }
98
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;
105   }
106   virtual void OnConnected(SocketStream* socket,
107                            int max_pending_send_allowed) OVERRIDE {
108     if (!on_connected_.is_null())
109       on_connected_.Run();
110   }
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();
116   }
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();
122   }
123   virtual void OnClose(SocketStream* socket) OVERRIDE {
124     if (!on_close_.is_null())
125       on_close_.Run();
126   }
127   virtual bool CanGetCookies(SocketStream* socket,
128                              const GURL& url) OVERRIDE {
129     return allow_all_cookies_;
130   }
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_;
136   }
137
138   size_t amount_sent() const { return amount_sent_; }
139   const std::string& received_data() const { return received_data_; }
140
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_;
150 };
151
152 class MockCookieStore : public CookieStore {
153  public:
154   struct Entry {
155     GURL url;
156     std::string cookie_line;
157     CookieOptions options;
158   };
159
160   MockCookieStore() {}
161
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;
171   }
172
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 += "; ";
181         }
182         result += entry.cookie_line;
183       }
184     }
185     return result;
186   }
187
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);
197   }
198
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));
205   }
206
207   virtual void GetAllCookiesForURLAsync(
208       const GURL& url,
209       const GetCookieListCallback& callback) OVERRIDE {
210     ADD_FAILURE();
211   }
212
213   virtual void DeleteCookieAsync(const GURL& url,
214                                  const std::string& cookie_name,
215                                  const base::Closure& callback) OVERRIDE {
216     ADD_FAILURE();
217   }
218
219   virtual void DeleteAllCreatedBetweenAsync(
220       const base::Time& delete_begin,
221       const base::Time& delete_end,
222       const DeleteCallback& callback) OVERRIDE {
223     ADD_FAILURE();
224   }
225
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();
232   }
233
234   virtual void DeleteSessionCookiesAsync(const DeleteCallback&) OVERRIDE {
235     ADD_FAILURE();
236   }
237
238   virtual CookieMonster* GetCookieMonster() OVERRIDE { return NULL; }
239
240   const std::vector<Entry>& entries() const { return entries_; }
241
242  private:
243   friend class base::RefCountedThreadSafe<MockCookieStore>;
244   virtual ~MockCookieStore() {}
245
246   std::vector<Entry> entries_;
247 };
248
249 class MockSSLConfigService : public SSLConfigService {
250  public:
251   virtual void GetSSLConfig(SSLConfig* config) OVERRIDE {}
252
253  protected:
254   virtual ~MockSSLConfigService() {}
255 };
256
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);
267   }
268
269   virtual ~MockURLRequestContext() {
270     AssertNoURLRequests();
271   }
272
273  private:
274   TransportSecurityState transport_security_state_;
275 };
276
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());
297   }
298
299   virtual int CreateTransaction(
300       RequestPriority priority,
301       scoped_ptr<HttpTransaction>* trans) OVERRIDE {
302     NOTREACHED();
303     return ERR_UNEXPECTED;
304   }
305
306   virtual HttpCache* GetCache() OVERRIDE {
307     NOTREACHED();
308     return NULL;
309   }
310
311   virtual HttpNetworkSession* GetSession() OVERRIDE {
312     return http_session_.get();
313   }
314
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_;
322 };
323
324 class DeletingSocketStreamDelegate : public SocketStream::Delegate {
325  public:
326   DeletingSocketStreamDelegate()
327       : delete_next_(false) {}
328
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(); }
333
334   void set_job(WebSocketJob* job) { job_ = job; }
335
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; }
339
340   void DeleteJobMaybe() {
341     if (delete_next_) {
342       job_->DetachContext();
343       job_->DetachDelegate();
344       job_ = NULL;
345     }
346   }
347
348   // SocketStream::Delegate implementation
349
350   // OnStartOpenConnection() is not implemented by SocketStreamDispatcherHost
351
352   virtual void OnConnected(SocketStream* socket,
353                            int max_pending_send_allowed) OVERRIDE {
354     DeleteJobMaybe();
355   }
356
357   virtual void OnSentData(SocketStream* socket, int amount_sent) OVERRIDE {
358     DeleteJobMaybe();
359   }
360
361   virtual void OnReceivedData(SocketStream* socket,
362                               const char* data,
363                               int len) OVERRIDE {
364     DeleteJobMaybe();
365   }
366
367   virtual void OnClose(SocketStream* socket) OVERRIDE { DeleteJobMaybe(); }
368
369   virtual void OnAuthRequired(SocketStream* socket,
370                               AuthChallengeInfo* auth_info) OVERRIDE {
371     DeleteJobMaybe();
372   }
373
374   virtual void OnSSLCertificateError(SocketStream* socket,
375                                      const SSLInfo& ssl_info,
376                                      bool fatal) OVERRIDE {
377     DeleteJobMaybe();
378   }
379
380   virtual void OnError(const SocketStream* socket, int error) OVERRIDE {
381     DeleteJobMaybe();
382   }
383
384   // CanGetCookies() and CanSetCookies() do not appear to be able to delete the
385   // WebSocketJob object.
386
387  private:
388   scoped_refptr<WebSocketJob> job_;
389   bool delete_next_;
390 };
391
392 }  // namespace
393
394 class WebSocketJobTest : public PlatformTest,
395                          public ::testing::WithParamInterface<NextProto> {
396  public:
397   WebSocketJobTest()
398       : spdy_util_(GetParam()),
399         enable_websocket_over_spdy_(false) {}
400
401   virtual void SetUp() OVERRIDE {
402     stream_type_ = STREAM_INVALID;
403     cookie_store_ = new MockCookieStore;
404     context_.reset(new MockURLRequestContext(cookie_store_.get()));
405   }
406   virtual void TearDown() OVERRIDE {
407     cookie_store_ = NULL;
408     context_.reset();
409     websocket_ = NULL;
410     socket_ = NULL;
411   }
412   void DoSendRequest() {
413     EXPECT_TRUE(websocket_->SendData(kHandshakeRequestWithoutCookie,
414                                      kHandshakeRequestWithoutCookieLength));
415   }
416   void DoSendData() {
417     if (received_data().size() == kHandshakeResponseWithoutCookieLength)
418       websocket_->SendData(kDataHello, kDataHelloLength);
419   }
420   void DoSync() {
421     sync_test_callback_.callback().Run(OK);
422   }
423   int WaitForResult() {
424     return sync_test_callback_.WaitForResult();
425   }
426
427  protected:
428   enum StreamType {
429     STREAM_INVALID,
430     STREAM_MOCK_SOCKET,
431     STREAM_SOCKET,
432     STREAM_SPDY_WEBSOCKET,
433   };
434   enum ThrottlingOption {
435     THROTTLING_OFF,
436     THROTTLING_ON,
437   };
438   enum SpdyOption {
439     SPDY_OFF,
440     SPDY_ON,
441   };
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);
448
449     if (stream_type == STREAM_MOCK_SOCKET)
450       socket_ = new MockSocketStream(url, websocket_.get(), context_.get(),
451                                      NULL);
452
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());
458       }
459
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());
466
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());
472     }
473
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);
482   }
483   void SkipToConnecting() {
484     websocket_->state_ = WebSocketJob::CONNECTING;
485     ASSERT_TRUE(WebSocketThrottle::GetInstance()->PutInQueue(websocket_.get()));
486   }
487   WebSocketJob::State GetWebSocketJobState() {
488     return websocket_->state_;
489   }
490   void CloseWebSocketJob() {
491     if (websocket_->socket_.get()) {
492       websocket_->socket_->DetachDelegate();
493       WebSocketThrottle::GetInstance()->RemoveFromQueue(websocket_.get());
494     }
495     websocket_->state_ = WebSocketJob::CLOSED;
496     websocket_->delegate_ = NULL;
497     websocket_->socket_ = NULL;
498   }
499   SocketStream* GetSocket(SocketStreamJob* job) {
500     return job->socket_.get();
501   }
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();
508   }
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();
515   }
516
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();
526
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_;
540
541   // Must be set before call to enable_websocket_over_spdy, defaults to false.
542   bool enable_websocket_over_spdy_;
543
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;
560 };
561
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);
574
575     socket_ = new MockSocketStream(
576         GURL("ws://127.0.0.1/"), websocket, context_.get(), NULL);
577
578     websocket->InitSocketStream(socket_.get());
579   }
580
581   void SetDeleteNext() { return delegate_->set_delete_next(true); }
582   WebSocketJob* job() { return delegate_->job(); }
583
584   scoped_ptr<DeletingSocketStreamDelegate> delegate_;
585   scoped_refptr<MockCookieStore> cookie_store_;
586   scoped_ptr<MockURLRequestContext> context_;
587   scoped_refptr<SocketStream> socket_;
588 };
589
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";
600
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";
612
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";
624
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";
632
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";
641
642 const char WebSocketJobTest::kDataHello[] = "Hello, ";
643
644 const char WebSocketJobTest::kDataWorld[] = "World!\n";
645
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;
660
661 void WebSocketJobTest::TestSimpleHandshake() {
662   GURL url("ws://example.com/demo");
663   MockSocketStreamDelegate delegate;
664   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
665   SkipToConnecting();
666
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());
674
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();
682 }
683
684 void WebSocketJobTest::TestSlowHandshake() {
685   GURL url("ws://example.com/demo");
686   MockSocketStreamDelegate delegate;
687   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
688   SkipToConnecting();
689
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());
699
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());
709   }
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();
716 }
717
718 INSTANTIATE_TEST_CASE_P(
719     NextProto,
720     WebSocketJobTest,
721     testing::Values(kProtoDeprecatedSPDY2,
722                     kProtoSPDY3, kProtoSPDY31, kProtoSPDY4));
723
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());
739
740   MockSocketStreamDelegate delegate;
741   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
742   SkipToConnecting();
743
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());
754
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());
761
762   CloseWebSocketJob();
763 }
764
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);
774
775   MockSocketStreamDelegate delegate;
776   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
777   SkipToConnecting();
778
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());
789
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());
796
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);
804
805   CloseWebSocketJob();
806 }
807
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);
817
818   MockSocketStreamDelegate delegate;
819   delegate.set_allow_all_cookies(false);
820   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
821   SkipToConnecting();
822
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());
831
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());
838
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);
844
845   CloseWebSocketJob();
846 }
847
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();
857
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();
864 }
865
866 void WebSocketJobTest::TestInvalidSendData() {
867   GURL url("ws://example.com/demo");
868   MockSocketStreamDelegate delegate;
869   InitWebSocketJob(url, &delegate, STREAM_MOCK_SOCKET);
870   SkipToConnecting();
871
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());
881
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();
888 }
889
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.
896
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,
907               1),
908     MockWrite(ASYNC,
909               kDataHello,
910               kDataHelloLength,
911               3)
912   };
913   MockRead reads[] = {
914     MockRead(ASYNC,
915              kHandshakeResponseWithoutCookie,
916              kHandshakeResponseWithoutCookieLength,
917              2),
918     MockRead(ASYNC,
919              kDataWorld,
920              kDataWorldLength,
921              4),
922     MockRead(SYNCHRONOUS, 0, 5)  // EOF
923   };
924   data_.reset(new OrderedSocketData(
925       reads, arraysize(reads), writes, arraysize(writes)));
926
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);
941
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()));
949   }
950
951   websocket_->Connect();
952
953   if (throttling == THROTTLING_ON) {
954     EXPECT_EQ(OK, WaitForResult());
955     EXPECT_TRUE(websocket_->IsWaiting());
956
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;
962   }
963
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());
968 }
969
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,
981               1),
982     MockWrite(ASYNC,
983               kDataHello,
984               kDataHelloLength,
985               3)
986   };
987   MockRead reads_websocket[] = {
988     MockRead(ASYNC,
989              kHandshakeResponseWithoutCookie,
990              kHandshakeResponseWithoutCookieLength,
991              2),
992     MockRead(ASYNC,
993              kDataWorld,
994              kDataWorldLength,
995              4),
996     MockRead(SYNCHRONOUS, 0, 5)  // EOF
997   };
998
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());
1007
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());
1013
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),
1040   };
1041   MockRead reads_spdy[] = {
1042     CreateMockRead(*response_frame.get(), 2),
1043     CreateMockRead(*data_world_frame.get(), 4),
1044     MockRead(SYNCHRONOUS, 0, 5)  // EOF
1045   };
1046
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)));
1055
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);
1070
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()));
1078   }
1079
1080   websocket_->Connect();
1081
1082   if (throttling == THROTTLING_ON) {
1083     EXPECT_EQ(OK, WaitForResult());
1084     EXPECT_TRUE(websocket_->IsWaiting());
1085
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;
1091   }
1092
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());
1097 }
1098
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);
1112   }
1113
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);
1123   }
1124 }
1125
1126 // Execute tests in both spdy-disabled mode and spdy-enabled mode.
1127 TEST_P(WebSocketJobTest, SimpleHandshake) {
1128   TestSimpleHandshake();
1129 }
1130
1131 TEST_P(WebSocketJobTest, SlowHandshake) {
1132   TestSlowHandshake();
1133 }
1134
1135 TEST_P(WebSocketJobTest, HandshakeWithCookie) {
1136   TestHandshakeWithCookie();
1137 }
1138
1139 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowed) {
1140   TestHandshakeWithCookieButNotAllowed();
1141 }
1142
1143 TEST_P(WebSocketJobTest, HSTSUpgrade) {
1144   TestHSTSUpgrade();
1145 }
1146
1147 TEST_P(WebSocketJobTest, InvalidSendData) {
1148   TestInvalidSendData();
1149 }
1150
1151 TEST_P(WebSocketJobTest, SimpleHandshakeSpdyEnabled) {
1152   enable_websocket_over_spdy_ = true;
1153   TestSimpleHandshake();
1154 }
1155
1156 TEST_P(WebSocketJobTest, SlowHandshakeSpdyEnabled) {
1157   enable_websocket_over_spdy_ = true;
1158   TestSlowHandshake();
1159 }
1160
1161 TEST_P(WebSocketJobTest, HandshakeWithCookieSpdyEnabled) {
1162   enable_websocket_over_spdy_ = true;
1163   TestHandshakeWithCookie();
1164 }
1165
1166 TEST_P(WebSocketJobTest, HandshakeWithCookieButNotAllowedSpdyEnabled) {
1167   enable_websocket_over_spdy_ = true;
1168   TestHandshakeWithCookieButNotAllowed();
1169 }
1170
1171 TEST_P(WebSocketJobTest, HSTSUpgradeSpdyEnabled) {
1172   enable_websocket_over_spdy_ = true;
1173   TestHSTSUpgrade();
1174 }
1175
1176 TEST_P(WebSocketJobTest, InvalidSendDataSpdyEnabled) {
1177   enable_websocket_over_spdy_ = true;
1178   TestInvalidSendData();
1179 }
1180
1181 TEST_P(WebSocketJobTest, ConnectByWebSocket) {
1182   enable_websocket_over_spdy_ = true;
1183   TestConnectByWebSocket(THROTTLING_OFF);
1184 }
1185
1186 TEST_P(WebSocketJobTest, ConnectByWebSocketSpdyEnabled) {
1187   enable_websocket_over_spdy_ = true;
1188   TestConnectByWebSocket(THROTTLING_OFF);
1189 }
1190
1191 TEST_P(WebSocketJobTest, ConnectBySpdy) {
1192   TestConnectBySpdy(SPDY_OFF, THROTTLING_OFF);
1193 }
1194
1195 TEST_P(WebSocketJobTest, ConnectBySpdySpdyEnabled) {
1196   enable_websocket_over_spdy_ = true;
1197   TestConnectBySpdy(SPDY_ON, THROTTLING_OFF);
1198 }
1199
1200 TEST_P(WebSocketJobTest, ThrottlingWebSocket) {
1201   TestConnectByWebSocket(THROTTLING_ON);
1202 }
1203
1204 TEST_P(WebSocketJobTest, ThrottlingMaxNumberOfThrottledJobLimit) {
1205   TestThrottlingLimit();
1206 }
1207
1208 TEST_P(WebSocketJobTest, ThrottlingWebSocketSpdyEnabled) {
1209   enable_websocket_over_spdy_ = true;
1210   TestConnectByWebSocket(THROTTLING_ON);
1211 }
1212
1213 TEST_P(WebSocketJobTest, ThrottlingSpdy) {
1214   TestConnectBySpdy(SPDY_OFF, THROTTLING_ON);
1215 }
1216
1217 TEST_P(WebSocketJobTest, ThrottlingSpdySpdyEnabled) {
1218   enable_websocket_over_spdy_ = true;
1219   TestConnectBySpdy(SPDY_ON, THROTTLING_ON);
1220 }
1221
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());
1232 }
1233
1234 TEST_F(WebSocketJobDeleteTest, OnAuthRequired) {
1235   SetDeleteNext();
1236   job()->OnAuthRequired(socket_.get(), NULL);
1237   EXPECT_FALSE(job());
1238 }
1239
1240 TEST_F(WebSocketJobDeleteTest, OnSSLCertificateError) {
1241   SSLInfo ssl_info;
1242   SetDeleteNext();
1243   job()->OnSSLCertificateError(socket_.get(), ssl_info, true);
1244   EXPECT_FALSE(job());
1245 }
1246
1247 TEST_F(WebSocketJobDeleteTest, OnError) {
1248   SetDeleteNext();
1249   job()->OnError(socket_.get(), ERR_CONNECTION_RESET);
1250   EXPECT_FALSE(job());
1251 }
1252
1253 TEST_F(WebSocketJobDeleteTest, OnSentSpdyHeaders) {
1254   job()->Connect();
1255   SetDeleteNext();
1256   job()->OnSentSpdyHeaders();
1257   EXPECT_FALSE(job());
1258 }
1259
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());
1276 }
1277
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());
1290 }
1291
1292 // TODO(toyoshim): Add tests to verify throttling, SPDY stream limitation.
1293 // TODO(toyoshim,yutak): Add tests to verify closing handshake.
1294 }  // namespace net