158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/websockets/websocket_throttle.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/address_list.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/test_completion_callback.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket_stream/socket_stream.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_test_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/websockets/websocket_job.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/platform_test.h"
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DummySocketStreamDelegate : public net::SocketStream::Delegate {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DummySocketStreamDelegate() {}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DummySocketStreamDelegate() {}
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnConnected(
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net::SocketStream* socket, int max_pending_send_allowed) OVERRIDE {}
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnSentData(net::SocketStream* socket,
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          int amount_sent) OVERRIDE {}
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnReceivedData(net::SocketStream* socket,
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const char* data, int len) OVERRIDE {}
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void OnClose(net::SocketStream* socket) OVERRIDE {}
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class WebSocketThrottleTest : public PlatformTest {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static IPEndPoint MakeAddr(int a1, int a2, int a3, int a4) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    IPAddressNumber ip;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ip.push_back(a1);
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ip.push_back(a2);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ip.push_back(a3);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ip.push_back(a4);
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return IPEndPoint(ip, 0);
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void MockSocketStreamConnect(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SocketStream* socket, const AddressList& list) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket->set_addresses(list);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(toyoshim): We should introduce additional tests on cases via proxy.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    socket->proxy_info_.UseDirect();
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In SocketStream::Connect(), it adds reference to socket, which is
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // balanced with SocketStream::Finish() that is finally called from
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SocketStream::Close() or SocketStream::DetachDelegate(), when
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // next_state_ is not STATE_NONE.
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If next_state_ is STATE_NONE, SocketStream::Close() or
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SocketStream::DetachDelegate() won't call SocketStream::Finish(),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // so Release() won't be called.  Thus, we don't need socket->AddRef()
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // here.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(socket->next_state_, SocketStream::STATE_NONE);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(WebSocketThrottleTest, Throttle) {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DummySocketStreamDelegate delegate;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(toyoshim): We need to consider both spdy-enabled and spdy-disabled
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // configuration.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketJob::set_websocket_over_spdy_enabled(true);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For host1: 1.2.3.4, 1.2.3.5, 1.2.3.6
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddressList addr;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(1, 2, 3, 4));
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(1, 2, 3, 5));
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(1, 2, 3, 6));
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> w1(new WebSocketJob(&delegate));
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> s1(
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://host1/"), w1.get()));
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s1->set_context(&context);
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->InitSocketStream(s1.get());
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  WebSocketThrottleTest::MockSocketStreamConnect(s1.get(), addr);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket1";
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback_s1;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trying to open connection to host1 will start without wait.
84868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(OK, w1->OnStartOpenConnection(s1.get(), callback_s1.callback()));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now connecting to host1, so waiting queue looks like
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 | w1
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 | w1
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 | w1
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For host2: 1.2.3.4
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.clear();
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(1, 2, 3, 4));
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> w2(new WebSocketJob(&delegate));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> s2(
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://host2/"), w2.get()));
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s2->set_context(&context);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->InitSocketStream(s2.get());
100868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  WebSocketThrottleTest::MockSocketStreamConnect(s2.get(), addr);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket2";
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback_s2;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trying to open connection to host2 will wait for w1.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            w2->OnStartOpenConnection(s2.get(), callback_s2.callback()));
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now waiting queue looks like
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 | w1 w2
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 | w1
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 | w1
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For host3: 1.2.3.5
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.clear();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(1, 2, 3, 5));
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> w3(new WebSocketJob(&delegate));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> s3(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://host3/"), w3.get()));
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s3->set_context(&context);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w3->InitSocketStream(s3.get());
121868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  WebSocketThrottleTest::MockSocketStreamConnect(s3.get(), addr);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket3";
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback_s3;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trying to open connection to host3 will wait for w1.
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
127868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            w3->OnStartOpenConnection(s3.get(), callback_s3.callback()));
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 | w1 w2
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 | w1    w3
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 | w1
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For host4: 1.2.3.4, 1.2.3.6
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.clear();
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(1, 2, 3, 4));
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(1, 2, 3, 6));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> w4(new WebSocketJob(&delegate));
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> s4(
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://host4/"), w4.get()));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s4->set_context(&context);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w4->InitSocketStream(s4.get());
142868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  WebSocketThrottleTest::MockSocketStreamConnect(s4.get(), addr);
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket4";
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback_s4;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trying to open connection to host4 will wait for w1, w2.
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            w4->OnStartOpenConnection(s4.get(), callback_s4.callback()));
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 | w1 w2    w4
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 | w1    w3
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 | w1       w4
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For host5: 1.2.3.6
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.clear();
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(1, 2, 3, 6));
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> w5(new WebSocketJob(&delegate));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> s5(
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://host5/"), w5.get()));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s5->set_context(&context);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w5->InitSocketStream(s5.get());
162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  WebSocketThrottleTest::MockSocketStreamConnect(s5.get(), addr);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket5";
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback_s5;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trying to open connection to host5 will wait for w1, w4
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            w5->OnStartOpenConnection(s5.get(), callback_s5.callback()));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 | w1 w2    w4
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 | w1    w3
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 | w1       w4 w5
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For host6: 1.2.3.6
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.clear();
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(1, 2, 3, 6));
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> w6(new WebSocketJob(&delegate));
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> s6(
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://host6/"), w6.get()));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s6->set_context(&context);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w6->InitSocketStream(s6.get());
182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  WebSocketThrottleTest::MockSocketStreamConnect(s6.get(), addr);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket6";
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback_s6;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trying to open connection to host6 will wait for w1, w4, w5
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(ERR_IO_PENDING,
188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            w6->OnStartOpenConnection(s6.get(), callback_s6.callback()));
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 | w1 w2    w4
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 | w1    w3
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 | w1       w4 w5 w6
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Receive partial response on w1, still connecting.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket1 1";
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHeader[] = "HTTP/1.1 101 WebSocket Protocol\r\n";
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->OnReceivedData(s1.get(), kHeader, sizeof(kHeader) - 1);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback_s2.have_result());
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback_s3.have_result());
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback_s4.have_result());
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback_s5.have_result());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback_s6.have_result());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Receive rest of handshake response on w1.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket1 2";
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kHeader2[] =
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Upgrade: WebSocket\r\n"
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Connection: Upgrade\r\n"
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Origin: http://www.google.com\r\n"
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Sec-WebSocket-Location: ws://websocket.chromium.org\r\n"
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\r\n"
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "8jKS'y:G*Co,Wxa-";
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->OnReceivedData(s1.get(), kHeader2, sizeof(kHeader2) - 1);
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO::current()->RunUntilIdle();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now, w1 is open.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(WebSocketJob::OPEN, w1->state());
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // So, w2 and w3 can start connecting. w4 needs to wait w2 (1.2.3.4)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(callback_s2.have_result());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(callback_s3.have_result());
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback_s4.have_result());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 |    w2    w4
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 |       w3
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 |          w4 w5 w6
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Closing s1 doesn't change waiting queue.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket1 close";
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->OnClose(s1.get());
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO::current()->RunUntilIdle();
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback_s4.have_result());
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s1->DetachDelegate();
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 |    w2    w4
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 |       w3
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 |          w4 w5 w6
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // w5 can close while waiting in queue.
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket5 close";
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // w5 close() closes SocketStream that change state to STATE_CLOSE, calls
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // DoLoop(), so OnClose() callback will be called.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w5->OnClose(s5.get());
24290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO::current()->RunUntilIdle();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback_s4.have_result());
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 |    w2    w4
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 |       w3
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 |          w4 w6
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s5->DetachDelegate();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // w6 close abnormally (e.g. renderer finishes) while waiting in queue.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket6 close abnormally";
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w6->DetachDelegate();
25390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO::current()->RunUntilIdle();
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(callback_s4.have_result());
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 |    w2    w4
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 |       w3
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 |          w4
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Closing s2 kicks w4 to start connecting.
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket2 close";
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w2->OnClose(s2.get());
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO::current()->RunUntilIdle();
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(callback_s4.have_result());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Address | head -> tail
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.4 |          w4
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.5 |       w3
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1.2.3.6 |          w4
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s2->DetachDelegate();
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket3 close";
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w3->OnClose(s3.get());
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO::current()->RunUntilIdle();
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s3->DetachDelegate();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w4->OnClose(s4.get());
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s4->DetachDelegate();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Done";
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO::current()->RunUntilIdle();
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(WebSocketThrottleTest, NoThrottleForDuplicateAddress) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestURLRequestContext context;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DummySocketStreamDelegate delegate;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebSocketJob::set_websocket_over_spdy_enabled(true);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For localhost: 127.0.0.1, 127.0.0.1
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddressList addr;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(127, 0, 0, 1));
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  addr.push_back(MakeAddr(127, 0, 0, 1));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebSocketJob> w1(new WebSocketJob(&delegate));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<SocketStream> s1(
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new SocketStream(GURL("ws://localhost/"), w1.get()));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s1->set_context(&context);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->InitSocketStream(s1.get());
295868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  WebSocketThrottleTest::MockSocketStreamConnect(s1.get(), addr);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket1";
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestCompletionCallback callback_s1;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trying to open connection to localhost will start without wait.
300868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(OK, w1->OnStartOpenConnection(s1.get(), callback_s1.callback()));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "socket1 close";
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  w1->OnClose(s1.get());
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  s1->DetachDelegate();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "Done";
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO::current()->RunUntilIdle();
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A connection should not be blocked by another connection to the same IP
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// with a different port.
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(WebSocketThrottleTest, NoThrottleForDistinctPort) {
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestURLRequestContext context;
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DummySocketStreamDelegate delegate;
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  IPAddressNumber localhost;
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ParseIPLiteralToNumber("127.0.0.1", &localhost);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  WebSocketJob::set_websocket_over_spdy_enabled(false);
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // socket1: 127.0.0.1:80
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<WebSocketJob> w1(new WebSocketJob(&delegate));
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<SocketStream> s1(
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new SocketStream(GURL("ws://localhost:80/"), w1.get()));
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  s1->set_context(&context);
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  w1->InitSocketStream(s1.get());
324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MockSocketStreamConnect(s1.get(),
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          AddressList::CreateFromIPAddress(localhost, 80));
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "connecting socket1";
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestCompletionCallback callback_s1;
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Trying to open connection to localhost:80 will start without waiting.
330868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(OK, w1->OnStartOpenConnection(s1.get(), callback_s1.callback()));
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // socket2: 127.0.0.1:81
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<WebSocketJob> w2(new WebSocketJob(&delegate));
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<SocketStream> s2(
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new SocketStream(GURL("ws://localhost:81/"), w2.get()));
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  s2->set_context(&context);
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  w2->InitSocketStream(s2.get());
338868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MockSocketStreamConnect(s2.get(),
339868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          AddressList::CreateFromIPAddress(localhost, 81));
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "connecting socket2";
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TestCompletionCallback callback_s2;
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Trying to open connection to localhost:81 will start without waiting.
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(OK, w2->OnStartOpenConnection(s2.get(), callback_s2.callback()));
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "closing socket1";
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  w1->OnClose(s1.get());
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  s1->DetachDelegate();
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "closing socket2";
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  w2->OnClose(s2.get());
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  s2->DetachDelegate();
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DVLOG(1) << "Done";
35490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForIO::current()->RunUntilIdle();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
358