Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6839)

Unified Diff: chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc

Issue 18541: Add a constraint on how many requests can be outstanding for any given render (browser-side). (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/renderer_host/resource_dispatcher_host.cc ('k') | net/base/net_error_list.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc
===================================================================
--- chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc (revision 9239)
+++ chrome/browser/renderer_host/resource_dispatcher_host_unittest.cc (working copy)
@@ -104,7 +104,7 @@
URLRequest::RegisterProtocolFactory("test", NULL);
RendererSecurityPolicy::GetInstance()->Remove(0);
- // The plugin lib is automatically loaded during these test
+ // The plugin lib is automatically loaded during these test
// and we want a clean environment for other tests.
ChromePluginLib::UnloadAllPlugins();
@@ -194,6 +194,8 @@
// Tests whether many messages get dispatched properly.
TEST_F(ResourceDispatcherHostTest, TestMany) {
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1());
MakeTestRequest(0, 0, 2, URLRequestTestJob::test_url_2());
MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3());
@@ -201,6 +203,8 @@
// flush all the pending requests
while (URLRequestTestJob::ProcessOnePendingMessage());
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
// sorts out all the messages we saw by request
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
@@ -218,6 +222,8 @@
TEST_F(ResourceDispatcherHostTest, Cancel) {
ResourceDispatcherHost host(NULL);
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1());
MakeTestRequest(0, 0, 2, URLRequestTestJob::test_url_2());
MakeTestRequest(0, 0, 3, URLRequestTestJob::test_url_3());
@@ -225,7 +231,10 @@
// flush all the pending requests
while (URLRequestTestJob::ProcessOnePendingMessage());
+ MessageLoop::current()->RunAllPending();
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
@@ -235,28 +244,19 @@
CheckSuccessfulRequest(msgs[0], URLRequestTestJob::test_data_1());
CheckSuccessfulRequest(msgs[2], URLRequestTestJob::test_data_3());
- // Check that request 2 got canceled before it finished reading, which gives
- // us 1 ReceivedResponse message.
- ASSERT_EQ(1, msgs[1].size());
+ // Check that request 2 got canceled.
+ ASSERT_EQ(2, msgs[1].size());
ASSERT_EQ(ViewMsg_Resource_ReceivedResponse::ID, msgs[1][0].type());
+ ASSERT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[1][1].type());
- // TODO(mbelshe):
- // Now that the async IO path is in place, the IO always completes on the
- // initial call; so the cancel doesn't arrive until after we finished.
- // This basically means the test doesn't work.
-#if 0
int request_id;
URLRequestStatus status;
- // The message should be all data received with an error.
- ASSERT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[1][2].type());
-
void* iter = NULL;
- ASSERT_TRUE(IPC::ReadParam(&msgs[1][2], &iter, &request_id));
- ASSERT_TRUE(IPC::ReadParam(&msgs[1][2], &iter, &status));
+ ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &request_id));
+ ASSERT_TRUE(IPC::ReadParam(&msgs[1][1], &iter, &status));
EXPECT_EQ(URLRequestStatus::CANCELED, status.status());
-#endif
}
// Tests CancelRequestsForProcess
@@ -270,7 +270,7 @@
virtual bool Send(IPC::Message* msg) {
// no messages should be received when the process has been canceled
if (has_canceled_)
- received_after_canceled_ ++;
+ received_after_canceled_++;
delete msg;
return true;
}
@@ -283,6 +283,8 @@
ViewHostMsg_Resource_Request request =
CreateResourceRequest("GET", URLRequestTestJob::test_url_1());
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
host_.BeginRequest(&test_receiver, GetCurrentProcess(), 0, MSG_ROUTING_NONE,
1, request, NULL, NULL);
KickOffRequest();
@@ -296,7 +298,7 @@
3, request, NULL, NULL);
KickOffRequest();
- // TODO: mbelshe
+ // TODO(mbelshe):
// Now that the async IO path is in place, the IO always completes on the
// initial call; so the requests have already completed. This basically
// breaks the whole test.
@@ -314,6 +316,7 @@
while (URLRequestTestJob::ProcessOnePendingMessage());
EXPECT_EQ(0, host_.pending_requests());
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
// the test delegate should not have gotten any messages after being canceled
ASSERT_EQ(0, test_receiver.received_after_canceled_);
@@ -327,6 +330,8 @@
// Tests blocking and resuming requests.
TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
host_.BlockRequestsForRenderView(0, 1);
host_.BlockRequestsForRenderView(0, 2);
host_.BlockRequestsForRenderView(0, 3);
@@ -376,6 +381,8 @@
KickOffRequest();
while (URLRequestTestJob::ProcessOnePendingMessage());
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
msgs.clear();
accum_.GetClassifiedMessages(&msgs);
ASSERT_EQ(2, msgs.size());
@@ -385,6 +392,8 @@
// Tests blocking and canceling requests.
TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
host_.BlockRequestsForRenderView(0, 1);
MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1());
@@ -409,6 +418,9 @@
host_.CancelBlockedRequestsForRenderView(0, 1);
KickOffRequest();
while (URLRequestTestJob::ProcessOnePendingMessage());
+
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
msgs.clear();
accum_.GetClassifiedMessages(&msgs);
ASSERT_EQ(0, msgs.size());
@@ -416,6 +428,9 @@
// Tests that blocked requests are canceled if their associated process dies.
TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(1));
+
host_.BlockRequestsForRenderView(1, 0);
MakeTestRequest(0, 0, 1, URLRequestTestJob::test_url_1());
@@ -429,6 +444,9 @@
// Flush all the pending requests.
while (URLRequestTestJob::ProcessOnePendingMessage());
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(1));
+
// Sort out all the messages we saw by request.
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
@@ -461,3 +479,141 @@
// Flush all the pending requests.
while (URLRequestTestJob::ProcessOnePendingMessage());
}
+
+// Test the private helper method "CalculateApproximateMemoryCost()".
+TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
+ URLRequest req(GURL("http://www.google.com"), NULL);
+ EXPECT_EQ(4425, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req));
+
+ // Add 9 bytes of referrer.
+ req.set_referrer("123456789");
+ EXPECT_EQ(4434, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req));
+
+ // Add 33 bytes of upload content.
+ std::string upload_content;
+ upload_content.resize(33);
+ std::fill(upload_content.begin(), upload_content.end(), 'x');
+ req.AppendBytesToUpload(upload_content.data(), upload_content.size());
+
+ // Since the upload throttling is disabled, this has no effect on the cost.
+ EXPECT_EQ(4434, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req));
+
+ // Add a file upload -- should have no effect.
+ req.AppendFileToUpload(L"does-not-exist.png");
+ EXPECT_EQ(4434, ResourceDispatcherHost::CalculateApproximateMemoryCost(&req));
+}
+
+// Test the private helper method "IncrementOutstandingRequestsMemoryCost()".
+TEST_F(ResourceDispatcherHostTest, IncrementOutstandingRequestsMemoryCost) {
+ ResourceDispatcherHost host(NULL);
+
+ // Add some counts for render_process_host=7
+ EXPECT_EQ(0, host.GetOutstandingRequestsMemoryCost(7));
+ EXPECT_EQ(1, host.IncrementOutstandingRequestsMemoryCost(1, 7));
+ EXPECT_EQ(2, host.IncrementOutstandingRequestsMemoryCost(1, 7));
+ EXPECT_EQ(3, host.IncrementOutstandingRequestsMemoryCost(1, 7));
+
+ // Add some counts for render_process_host=3
+ EXPECT_EQ(0, host.GetOutstandingRequestsMemoryCost(3));
+ EXPECT_EQ(1, host.IncrementOutstandingRequestsMemoryCost(1, 3));
+ EXPECT_EQ(2, host.IncrementOutstandingRequestsMemoryCost(1, 3));
+
+ // Remove all the counts for render_process_host=7
+ EXPECT_EQ(3, host.GetOutstandingRequestsMemoryCost(7));
+ EXPECT_EQ(2, host.IncrementOutstandingRequestsMemoryCost(-1, 7));
+ EXPECT_EQ(1, host.IncrementOutstandingRequestsMemoryCost(-1, 7));
+ EXPECT_EQ(0, host.IncrementOutstandingRequestsMemoryCost(-1, 7));
+ EXPECT_EQ(0, host.GetOutstandingRequestsMemoryCost(7));
+
+ // Remove all the counts for render_process_host=3
+ EXPECT_EQ(2, host.GetOutstandingRequestsMemoryCost(3));
+ EXPECT_EQ(1, host.IncrementOutstandingRequestsMemoryCost(-1, 3));
+ EXPECT_EQ(0, host.IncrementOutstandingRequestsMemoryCost(-1, 3));
+ EXPECT_EQ(0, host.GetOutstandingRequestsMemoryCost(3));
+
+ // When an entry reaches 0, it should be deleted.
+ EXPECT_TRUE(host.outstanding_requests_memory_cost_map_.end() ==
+ host.outstanding_requests_memory_cost_map_.find(7));
+ EXPECT_TRUE(host.outstanding_requests_memory_cost_map_.end() ==
+ host.outstanding_requests_memory_cost_map_.find(3));
+}
+
+// Test that when too many requests are outstanding for a particular
+// render_process_host_id, any subsequent request from it fails.
+TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
+ // Expected cost of each request as measured by
+ // ResourceDispatcherHost::CalculateApproximateMemoryCost().
+ int kMemoryCostOfTest2Req =
+ ResourceDispatcherHost::kAvgBytesPerOutstandingRequest +
+ std::string("GET").size() +
+ URLRequestTestJob::test_url_2().spec().size();
+
+ // Tighten the bound on the ResourceDispatcherHost, to speed things up.
+ int kMaxCostPerProcess = 440000;
+ host_.set_max_outstanding_requests_cost_per_process(kMaxCostPerProcess);
+
+ // Determine how many instance of test_url_2() we can request before
+ // throttling kicks in.
+ int kMaxRequests = kMaxCostPerProcess / kMemoryCostOfTest2Req;
+
+ // Saturate the number of outstanding requests for process 0.
+ for (int i = 0; i < kMaxRequests; ++i)
+ MakeTestRequest(0, 0, i + 1, URLRequestTestJob::test_url_2());
+
+ // Issue two more requests for process 0 -- these should fail immediately.
+ MakeTestRequest(0, 0, kMaxRequests + 1, URLRequestTestJob::test_url_2());
+ MakeTestRequest(0, 0, kMaxRequests + 2, URLRequestTestJob::test_url_2());
+
+ // Issue two requests for process 1 -- these should succeed since
+ // it is just process 0 that is saturated.
+ MakeTestRequest(1, 0, kMaxRequests + 3, URLRequestTestJob::test_url_2());
+ MakeTestRequest(1, 0, kMaxRequests + 4, URLRequestTestJob::test_url_2());
+
+ // Flush all the pending requests.
+ while (URLRequestTestJob::ProcessOnePendingMessage());
+ MessageLoop::current()->RunAllPending();
+
+ EXPECT_EQ(0, host_.GetOutstandingRequestsMemoryCost(0));
+
+ // Sorts out all the messages we saw by request.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+
+ // We issued (kMaxRequests + 4) total requests.
+ ASSERT_EQ(kMaxRequests + 4, msgs.size());
+
+ // Check that the first kMaxRequests succeeded.
+ for (int i = 0; i < kMaxRequests; ++i)
+ CheckSuccessfulRequest(msgs[i], URLRequestTestJob::test_data_2());
+
+ // Check that the subsequent two requests (kMaxRequests + 1) and
+ // (kMaxRequests + 2) were failed, since the per-process bound was reached.
+ for (int i = 0; i < 2; ++i) {
+ // Should have sent a single RequestComplete message.
+ int index = kMaxRequests + i;
+ EXPECT_EQ(1, msgs[index].size());
+ EXPECT_EQ(ViewMsg_Resource_RequestComplete::ID, msgs[index][0].type());
+
+ // The RequestComplete message should have had status
+ // (CANCELLED, ERR_INSUFFICIENT_RESOURCES).
+ int request_id;
+ URLRequestStatus status;
+
+ void* iter = NULL;
+ EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &request_id));
+ EXPECT_TRUE(IPC::ReadParam(&msgs[index][0], &iter, &status));
+
+ EXPECT_EQ(index + 1, request_id);
+ EXPECT_EQ(URLRequestStatus::CANCELED, status.status());
+ EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES, status.os_error());
+ }
+
+ // The final 2 requests should have succeeded.
+ CheckSuccessfulRequest(msgs[kMaxRequests + 2],
+ URLRequestTestJob::test_data_2());
+ CheckSuccessfulRequest(msgs[kMaxRequests + 3],
+ URLRequestTestJob::test_data_2());
+}
+
« no previous file with comments | « chrome/browser/renderer_host/resource_dispatcher_host.cc ('k') | net/base/net_error_list.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698