| Index: net/websockets/websocket_throttle_unittest.cc
|
| diff --git a/net/websockets/websocket_throttle_unittest.cc b/net/websockets/websocket_throttle_unittest.cc
|
| index 55276e982fde444b47a5c9a1dde1feab1407ca72..d5682920a1825123c31a081d61230b6444f7cf28 100644
|
| --- a/net/websockets/websocket_throttle_unittest.cc
|
| +++ b/net/websockets/websocket_throttle_unittest.cc
|
| @@ -10,6 +10,7 @@
|
| #include "net/base/sys_addrinfo.h"
|
| #include "net/base/test_completion_callback.h"
|
| #include "net/socket_stream/socket_stream.h"
|
| +#include "net/websockets/websocket_job.h"
|
| #include "net/websockets/websocket_throttle.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| #include "testing/platform_test.h"
|
| @@ -66,94 +67,205 @@ class WebSocketThrottleTest : public PlatformTest {
|
| };
|
|
|
| TEST_F(WebSocketThrottleTest, Throttle) {
|
| - WebSocketThrottle::Init();
|
| DummySocketStreamDelegate delegate;
|
|
|
| - WebSocketThrottle* throttle = Singleton<WebSocketThrottle>::get();
|
| -
|
| - EXPECT_EQ(throttle,
|
| - SocketStreamThrottle::GetSocketStreamThrottleForScheme("ws"));
|
| - EXPECT_EQ(throttle,
|
| - SocketStreamThrottle::GetSocketStreamThrottleForScheme("wss"));
|
| -
|
| // For host1: 1.2.3.4, 1.2.3.5, 1.2.3.6
|
| struct addrinfo* addr = AddAddr(1, 2, 3, 4, NULL);
|
| addr = AddAddr(1, 2, 3, 5, addr);
|
| addr = AddAddr(1, 2, 3, 6, addr);
|
| + scoped_refptr<WebSocketJob> w1 = new WebSocketJob(&delegate);
|
| scoped_refptr<SocketStream> s1 =
|
| - new SocketStream(GURL("ws://host1/"), &delegate);
|
| + new SocketStream(GURL("ws://host1/"), w1.get());
|
| + w1->InitSocketStream(s1.get());
|
| WebSocketThrottleTest::SetAddressList(s1, addr);
|
| DeleteAddrInfo(addr);
|
|
|
| + DLOG(INFO) << "socket1";
|
| TestCompletionCallback callback_s1;
|
| - EXPECT_EQ(OK, throttle->OnStartOpenConnection(s1, &callback_s1));
|
| + // Trying to open connection to host1 will start without wait.
|
| + EXPECT_EQ(OK, w1->OnStartOpenConnection(s1, &callback_s1));
|
| +
|
| + // Now connecting to host1, so waiting queue looks like
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w1
|
| + // 1.2.3.5 | w1
|
| + // 1.2.3.6 | w1
|
|
|
| // For host2: 1.2.3.4
|
| addr = AddAddr(1, 2, 3, 4, NULL);
|
| + scoped_refptr<WebSocketJob> w2 = new WebSocketJob(&delegate);
|
| scoped_refptr<SocketStream> s2 =
|
| - new SocketStream(GURL("ws://host2/"), &delegate);
|
| + new SocketStream(GURL("ws://host2/"), w2.get());
|
| + w2->InitSocketStream(s2.get());
|
| WebSocketThrottleTest::SetAddressList(s2, addr);
|
| DeleteAddrInfo(addr);
|
|
|
| + DLOG(INFO) << "socket2";
|
| TestCompletionCallback callback_s2;
|
| - EXPECT_EQ(ERR_IO_PENDING, throttle->OnStartOpenConnection(s2, &callback_s2));
|
| + // Trying to open connection to host2 will wait for w1.
|
| + EXPECT_EQ(ERR_IO_PENDING, w2->OnStartOpenConnection(s2, &callback_s2));
|
| + // Now waiting queue looks like
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w1 w2
|
| + // 1.2.3.5 | w1
|
| + // 1.2.3.6 | w1
|
|
|
| // For host3: 1.2.3.5
|
| addr = AddAddr(1, 2, 3, 5, NULL);
|
| + scoped_refptr<WebSocketJob> w3 = new WebSocketJob(&delegate);
|
| scoped_refptr<SocketStream> s3 =
|
| - new SocketStream(GURL("ws://host3/"), &delegate);
|
| + new SocketStream(GURL("ws://host3/"), w3.get());
|
| + w3->InitSocketStream(s3.get());
|
| WebSocketThrottleTest::SetAddressList(s3, addr);
|
| DeleteAddrInfo(addr);
|
|
|
| + DLOG(INFO) << "socket3";
|
| TestCompletionCallback callback_s3;
|
| - EXPECT_EQ(ERR_IO_PENDING, throttle->OnStartOpenConnection(s3, &callback_s3));
|
| + // Trying to open connection to host3 will wait for w1.
|
| + EXPECT_EQ(ERR_IO_PENDING, w3->OnStartOpenConnection(s3, &callback_s3));
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w1 w2
|
| + // 1.2.3.5 | w1 w3
|
| + // 1.2.3.6 | w1
|
|
|
| // For host4: 1.2.3.4, 1.2.3.6
|
| addr = AddAddr(1, 2, 3, 4, NULL);
|
| addr = AddAddr(1, 2, 3, 6, addr);
|
| + scoped_refptr<WebSocketJob> w4 = new WebSocketJob(&delegate);
|
| scoped_refptr<SocketStream> s4 =
|
| - new SocketStream(GURL("ws://host4/"), &delegate);
|
| + new SocketStream(GURL("ws://host4/"), w4.get());
|
| + w4->InitSocketStream(s4.get());
|
| WebSocketThrottleTest::SetAddressList(s4, addr);
|
| DeleteAddrInfo(addr);
|
|
|
| + DLOG(INFO) << "socket4";
|
| TestCompletionCallback callback_s4;
|
| - EXPECT_EQ(ERR_IO_PENDING, throttle->OnStartOpenConnection(s4, &callback_s4));
|
| + // Trying to open connection to host4 will wait for w1, w2.
|
| + EXPECT_EQ(ERR_IO_PENDING, w4->OnStartOpenConnection(s4, &callback_s4));
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w1 w2 w4
|
| + // 1.2.3.5 | w1 w3
|
| + // 1.2.3.6 | w1 w4
|
| +
|
| + // For host5: 1.2.3.6
|
| + addr = AddAddr(1, 2, 3, 6, NULL);
|
| + scoped_refptr<WebSocketJob> w5 = new WebSocketJob(&delegate);
|
| + scoped_refptr<SocketStream> s5 =
|
| + new SocketStream(GURL("ws://host5/"), w5.get());
|
| + w5->InitSocketStream(s5.get());
|
| + WebSocketThrottleTest::SetAddressList(s5, addr);
|
| + DeleteAddrInfo(addr);
|
| +
|
| + DLOG(INFO) << "socket5";
|
| + TestCompletionCallback callback_s5;
|
| + // Trying to open connection to host5 will wait for w1, w4
|
| + EXPECT_EQ(ERR_IO_PENDING, w5->OnStartOpenConnection(s5, &callback_s5));
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w1 w2 w4
|
| + // 1.2.3.5 | w1 w3
|
| + // 1.2.3.6 | w1 w4 w5
|
| +
|
| + // For host6: 1.2.3.6
|
| + addr = AddAddr(1, 2, 3, 6, NULL);
|
| + scoped_refptr<WebSocketJob> w6 = new WebSocketJob(&delegate);
|
| + scoped_refptr<SocketStream> s6 =
|
| + new SocketStream(GURL("ws://host6/"), w6.get());
|
| + w6->InitSocketStream(s6.get());
|
| + WebSocketThrottleTest::SetAddressList(s6, addr);
|
| + DeleteAddrInfo(addr);
|
|
|
| + DLOG(INFO) << "socket6";
|
| + TestCompletionCallback callback_s6;
|
| + // Trying to open connection to host6 will wait for w1, w4, w5
|
| + EXPECT_EQ(ERR_IO_PENDING, w6->OnStartOpenConnection(s6, &callback_s6));
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w1 w2 w4
|
| + // 1.2.3.5 | w1 w3
|
| + // 1.2.3.6 | w1 w4 w5 w6
|
| +
|
| + // Receive partial response on w1, still connecting.
|
| + DLOG(INFO) << "socket1 1";
|
| static const char kHeader[] = "HTTP/1.1 101 Web Socket Protocol\r\n";
|
| - EXPECT_EQ(OK,
|
| - throttle->OnRead(s1.get(), kHeader, sizeof(kHeader) - 1, NULL));
|
| + w1->OnReceivedData(s1.get(), kHeader, sizeof(kHeader) - 1);
|
| EXPECT_FALSE(callback_s2.have_result());
|
| EXPECT_FALSE(callback_s3.have_result());
|
| EXPECT_FALSE(callback_s4.have_result());
|
| + EXPECT_FALSE(callback_s5.have_result());
|
| + EXPECT_FALSE(callback_s6.have_result());
|
|
|
| + // Receive rest of handshake response on w1.
|
| + DLOG(INFO) << "socket1 2";
|
| static const char kHeader2[] =
|
| "Upgrade: WebSocket\r\n"
|
| "Connection: Upgrade\r\n"
|
| "WebSocket-Origin: http://www.google.com\r\n"
|
| "WebSocket-Location: ws://websocket.chromium.org\r\n"
|
| "\r\n";
|
| - EXPECT_EQ(OK,
|
| - throttle->OnRead(s1.get(), kHeader2, sizeof(kHeader2) - 1, NULL));
|
| + w1->OnReceivedData(s1.get(), kHeader2, sizeof(kHeader2) - 1);
|
| MessageLoopForIO::current()->RunAllPending();
|
| + // Now, w1 is open.
|
| + EXPECT_EQ(WebSocketJob::OPEN, w1->state());
|
| + // So, w2 and w3 can start connecting. w4 needs to wait w2 (1.2.3.4)
|
| EXPECT_TRUE(callback_s2.have_result());
|
| EXPECT_TRUE(callback_s3.have_result());
|
| EXPECT_FALSE(callback_s4.have_result());
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w2 w4
|
| + // 1.2.3.5 | w3
|
| + // 1.2.3.6 | w4 w5 w6
|
|
|
| - throttle->OnClose(s1.get());
|
| + // Closing s1 doesn't change waiting queue.
|
| + DLOG(INFO) << "socket1 close";
|
| + w1->OnClose(s1.get());
|
| MessageLoopForIO::current()->RunAllPending();
|
| EXPECT_FALSE(callback_s4.have_result());
|
| s1->DetachDelegate();
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w2 w4
|
| + // 1.2.3.5 | w3
|
| + // 1.2.3.6 | w4 w5 w6
|
| +
|
| + // w5 can close while waiting in queue.
|
| + DLOG(INFO) << "socket5 close";
|
| + // w5 close() closes SocketStream that change state to STATE_CLOSE, calls
|
| + // DoLoop(), so OnClose() callback will be called.
|
| + w5->OnClose(s5.get());
|
| + MessageLoopForIO::current()->RunAllPending();
|
| + EXPECT_FALSE(callback_s4.have_result());
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w2 w4
|
| + // 1.2.3.5 | w3
|
| + // 1.2.3.6 | w4 w6
|
| + s5->DetachDelegate();
|
| +
|
| + // w6 close abnormally (e.g. renderer finishes) while waiting in queue.
|
| + DLOG(INFO) << "socket6 close abnormally";
|
| + w6->DetachDelegate();
|
| + MessageLoopForIO::current()->RunAllPending();
|
| + EXPECT_FALSE(callback_s4.have_result());
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w2 w4
|
| + // 1.2.3.5 | w3
|
| + // 1.2.3.6 | w4
|
|
|
| - throttle->OnClose(s2.get());
|
| + // Closing s2 kicks w4 to start connecting.
|
| + DLOG(INFO) << "socket2 close";
|
| + w2->OnClose(s2.get());
|
| MessageLoopForIO::current()->RunAllPending();
|
| EXPECT_TRUE(callback_s4.have_result());
|
| + // Address | head -> tail
|
| + // 1.2.3.4 | w4
|
| + // 1.2.3.5 | w3
|
| + // 1.2.3.6 | w4
|
| s2->DetachDelegate();
|
|
|
| - throttle->OnClose(s3.get());
|
| + DLOG(INFO) << "socket3 close";
|
| + w3->OnClose(s3.get());
|
| MessageLoopForIO::current()->RunAllPending();
|
| s3->DetachDelegate();
|
| - throttle->OnClose(s4.get());
|
| + w4->OnClose(s4.get());
|
| s4->DetachDelegate();
|
| + DLOG(INFO) << "Done";
|
| }
|
|
|
| }
|
|
|