Index: content/browser/renderer_host/websocket_dispatcher_host_unittest.cc |
diff --git a/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc b/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc |
index 0d2e7057bbcef5c0d90dadebc580843114e208bd..4368f3218dba641bcf880dbab5ef0eee2e95956c 100644 |
--- a/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc |
+++ b/content/browser/renderer_host/websocket_dispatcher_host_unittest.cc |
@@ -11,10 +11,12 @@ |
#include "base/bind_helpers.h" |
#include "base/memory/ref_counted.h" |
#include "base/memory/weak_ptr.h" |
+#include "base/message_loop/message_loop.h" |
#include "content/browser/renderer_host/websocket_host.h" |
#include "content/common/websocket.h" |
#include "content/common/websocket_messages.h" |
#include "ipc/ipc_message.h" |
+#include "net/websockets/websocket_errors.h" |
#include "testing/gtest/include/gtest/gtest.h" |
#include "url/gurl.h" |
#include "url/origin.h" |
@@ -33,19 +35,30 @@ class MockWebSocketHost : public WebSocketHost { |
MockWebSocketHost(int routing_id, |
WebSocketDispatcherHost* dispatcher, |
net::URLRequestContext* url_request_context, |
+ base::TimeDelta delay, |
WebSocketDispatcherHostTest* owner); |
~MockWebSocketHost() override {} |
bool OnMessageReceived(const IPC::Message& message) override { |
received_messages_.push_back(message); |
- return true; |
+ switch (message.type()) { |
+ case WebSocketMsg_DropChannel::ID: |
+ // Needed for PerRendererThrottlingFailedHandshakes, because without |
+ // calling WebSocketHost::OnMessageReceived() (and thus |
+ // WebSocketHost::OnDropChannel()), the connection stays pending and |
+ // we cannot test per-renderer throttling with failed connections. |
+ return WebSocketHost::OnMessageReceived(message); |
+ default: |
Adam Rice
2015/03/06 11:01:06
Blank line above default: please.
hiroshige
2015/03/11 06:21:25
Done.
|
+ return true; |
+ } |
} |
void GoAway() override; |
std::vector<IPC::Message> received_messages_; |
base::WeakPtr<WebSocketDispatcherHostTest> owner_; |
+ base::TimeDelta delay_; |
}; |
class WebSocketDispatcherHostTest : public ::testing::Test { |
@@ -82,6 +95,8 @@ class WebSocketDispatcherHostTest : public ::testing::Test { |
std::vector<MockWebSocketHost*> mock_hosts_; |
std::vector<int> gone_hosts_; |
+ base::MessageLoop message_loop_; |
+ |
base::WeakPtrFactory<WebSocketDispatcherHostTest> weak_ptr_factory_; |
private: |
@@ -89,9 +104,9 @@ class WebSocketDispatcherHostTest : public ::testing::Test { |
return NULL; |
} |
- WebSocketHost* CreateWebSocketHost(int routing_id) { |
- MockWebSocketHost* host = |
- new MockWebSocketHost(routing_id, dispatcher_host_.get(), NULL, this); |
+ WebSocketHost* CreateWebSocketHost(int routing_id, base::TimeDelta delay) { |
+ MockWebSocketHost* host = new MockWebSocketHost( |
+ routing_id, dispatcher_host_.get(), NULL, delay, this); |
mock_hosts_.push_back(host); |
return host; |
} |
@@ -101,9 +116,11 @@ MockWebSocketHost::MockWebSocketHost( |
int routing_id, |
WebSocketDispatcherHost* dispatcher, |
net::URLRequestContext* url_request_context, |
+ base::TimeDelta delay, |
WebSocketDispatcherHostTest* owner) |
- : WebSocketHost(routing_id, dispatcher, url_request_context), |
- owner_(owner->GetWeakPtr()) {} |
+ : WebSocketHost(routing_id, dispatcher, url_request_context, delay), |
+ owner_(owner->GetWeakPtr()), |
+ delay_(delay) {} |
void MockWebSocketHost::GoAway() { |
if (owner_) |
@@ -215,5 +232,86 @@ TEST_F(WebSocketDispatcherHostTest, Destruct) { |
EXPECT_EQ(456, gone_hosts_[1]); |
} |
+TEST_F(WebSocketDispatcherHostTest, PerRendererThrottling) { |
Adam Rice
2015/03/06 11:01:06
Please split this into three separate unit tests f
hiroshige
2015/03/11 06:21:25
Done.
|
+ GURL socket_url("ws://example.com/test"); |
+ std::vector<std::string> requested_protocols; |
+ requested_protocols.push_back("hello"); |
Adam Rice
2015/03/06 11:01:06
This makes no difference to the outcome of the tes
hiroshige
2015/03/11 06:21:25
Done.
|
+ url::Origin origin("http://example.com/test"); |
Adam Rice
2015/03/06 11:01:06
An origin never contains a path. It should be just
hiroshige
2015/03/11 06:21:24
Done. Also fixed other tests in this file.
|
+ int render_frame_id = -3; |
+ |
+ for (int i = 0; i < 256; ++i) { |
Adam Rice
2015/03/06 11:01:06
Since you are going to need this in several tests,
hiroshige
2015/03/11 06:21:25
Done.
Omitted |url| parameter because there is no
|
+ int routing_id = 123 + i; |
+ WebSocketHostMsg_AddChannelRequest message( |
+ routing_id, socket_url, requested_protocols, origin, render_frame_id); |
+ ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message)); |
+ } |
+ |
+ // The first 255 connections are added to mock_hosts_, staying pending. |
+ // The 256th connection is rejected. |
+ ASSERT_EQ(255U, mock_hosts_.size()); |
+ |
+// For the 1st--4th pending WebSocketHosts, delay is 0. |
+ for (int i = 0; i < 4; ++i) { |
+ MockWebSocketHost* host = mock_hosts_[i]; |
+ EXPECT_EQ(host->delay_, base::TimeDelta()); |
+ } |
+ |
+// For the 8th--16th pending WebSocketHosts, delay is > 0. |
+ for (int i = 7; i < 16; ++i) { |
+ MockWebSocketHost* host = mock_hosts_[i]; |
+ EXPECT_GT(host->delay_, base::TimeDelta()); |
+ } |
+ |
+// For the 17th-- pending WebSocketHosts, delay is >=1000 and <= 5000. |
+ for (int i = 16; i < 255; ++i) { |
Adam Rice
2015/03/06 11:01:06
You don't need to test every number. Tests should
hiroshige
2015/03/11 06:21:25
Done.
|
+ MockWebSocketHost* host = mock_hosts_[i]; |
+ EXPECT_GE(host->delay_, base::TimeDelta::FromMilliseconds(1000)); |
+ EXPECT_LE(host->delay_, base::TimeDelta::FromMilliseconds(5000)); |
+ } |
+} |
+ |
+TEST_F(WebSocketDispatcherHostTest, PerRendererThrottlingFailedHandshakes) { |
+ GURL socket_url("ws://example.com/test"); |
+ std::vector<std::string> requested_protocols; |
+ requested_protocols.push_back("hello"); |
+ url::Origin origin("http://example.com/test"); |
+ int render_frame_id = -4; |
+ |
+ // 256 AddChannelRequest are sent but are cancelled by DropChannel during |
Adam Rice
2015/03/06 11:01:06
s/during/while/
hiroshige
2015/03/11 06:21:25
Done.
|
+ // they are pending. They are counted as failure. |
+ // Delay is increased by the increasing number of failures. |
+ // However, the number of pending connections stays <= 1, so no connections |
+ // are rejected. |
+ for (int i = 0; i < 256; ++i) { |
+ int routing_id = 123 + i; |
+ WebSocketHostMsg_AddChannelRequest message( |
+ routing_id, socket_url, requested_protocols, origin, render_frame_id); |
+ ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message)); |
+ |
+ ASSERT_EQ(static_cast<size_t>(i + 1), mock_hosts_.size()); |
+ |
+ MockWebSocketHost* host = mock_hosts_[i]; |
+ if (i < 4) { |
Adam Rice
2015/03/06 11:01:06
I like to avoid having if statements in tests beca
hiroshige
2015/03/11 06:21:25
Split into separate tests.
|
+ // For the 1st--4th WebSocketHosts, delay is 0. |
+ EXPECT_EQ(host->delay_, base::TimeDelta()); |
+ } |
+ else if (7 <= i && i < 16) { |
+ // For the 8th--16th WebSocketHosts, delay is > 0. |
+ EXPECT_GT(host->delay_, base::TimeDelta()); |
+ } |
+ else if (16 <= i) { |
+ // For the 17th-- WebSocketHosts, delay is >=1000 and <= 5000. |
+ EXPECT_GE(host->delay_, base::TimeDelta::FromMilliseconds(1000)); |
+ EXPECT_LE(host->delay_, base::TimeDelta::FromMilliseconds(5000)); |
+ } |
+ |
+ WebSocketMsg_DropChannel message2( |
+ routing_id, false, net::kWebSocketErrorAbnormalClosure, ""); |
+ ASSERT_TRUE(dispatcher_host_->OnMessageReceived(message2)); |
+ // The connection is cancelled before WebSocketChannel is created, and |
+ // thus counted as failure. |
+ } |
+} |
+ |
} // namespace |
} // namespace content |