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