| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/loader/resource_scheduler.h" |
| |
| #include "base/memory/scoped_vector.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/timer/mock_timer.h" |
| #include "base/timer/timer.h" |
| #include "content/browser/browser_thread_impl.h" |
| #include "content/browser/loader/resource_dispatcher_host_impl.h" |
| #include "content/browser/loader/resource_message_filter.h" |
| #include "content/browser/loader/resource_request_info_impl.h" |
| #include "content/common/resource_messages.h" |
| #include "content/public/browser/resource_context.h" |
| #include "content/public/browser/resource_controller.h" |
| #include "content/public/browser/resource_throttle.h" |
| #include "content/public/common/process_type.h" |
| #include "content/public/common/resource_type.h" |
| #include "net/base/host_port_pair.h" |
| #include "net/base/request_priority.h" |
| #include "net/http/http_server_properties_impl.h" |
| #include "net/url_request/url_request.h" |
| #include "net/url_request/url_request_test_util.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| class TestRequestFactory; |
| |
| const int kChildId = 30; |
| const int kRouteId = 75; |
| const int kChildId2 = 43; |
| const int kRouteId2 = 67; |
| const int kBackgroundChildId = 35; |
| const int kBackgroundRouteId = 43; |
| const int kBackgroundChildId2 = 54; |
| const int kBackgroundRouteId2 = 82; |
| |
| class TestRequest : public ResourceController { |
| public: |
| TestRequest(scoped_ptr<ResourceThrottle> throttle, |
| scoped_ptr<net::URLRequest> url_request) |
| : started_(false), |
| throttle_(throttle.Pass()), |
| url_request_(url_request.Pass()) { |
| throttle_->set_controller_for_testing(this); |
| } |
| virtual ~TestRequest() {} |
| |
| bool started() const { return started_; } |
| |
| void Start() { |
| bool deferred = false; |
| throttle_->WillStartRequest(&deferred); |
| started_ = !deferred; |
| } |
| |
| virtual void Cancel() OVERRIDE { |
| // Alert the scheduler that the request can be deleted. |
| throttle_.reset(0); |
| } |
| |
| const net::URLRequest* url_request() const { return url_request_.get(); } |
| |
| protected: |
| // ResourceController interface: |
| virtual void CancelAndIgnore() OVERRIDE {} |
| virtual void CancelWithError(int error_code) OVERRIDE {} |
| virtual void Resume() OVERRIDE { started_ = true; } |
| |
| private: |
| bool started_; |
| scoped_ptr<ResourceThrottle> throttle_; |
| scoped_ptr<net::URLRequest> url_request_; |
| }; |
| |
| class CancelingTestRequest : public TestRequest { |
| public: |
| CancelingTestRequest(scoped_ptr<ResourceThrottle> throttle, |
| scoped_ptr<net::URLRequest> url_request) |
| : TestRequest(throttle.Pass(), url_request.Pass()) {} |
| |
| void set_request_to_cancel(scoped_ptr<TestRequest> request_to_cancel) { |
| request_to_cancel_ = request_to_cancel.Pass(); |
| } |
| |
| private: |
| virtual void Resume() OVERRIDE { |
| TestRequest::Resume(); |
| request_to_cancel_.reset(); |
| } |
| |
| scoped_ptr<TestRequest> request_to_cancel_; |
| }; |
| |
| class FakeResourceContext : public ResourceContext { |
| private: |
| virtual net::HostResolver* GetHostResolver() OVERRIDE { return NULL; } |
| virtual net::URLRequestContext* GetRequestContext() OVERRIDE { return NULL; } |
| virtual bool AllowMicAccess(const GURL& origin) OVERRIDE { return false; } |
| virtual bool AllowCameraAccess(const GURL& origin) OVERRIDE { return false; } |
| }; |
| |
| class FakeResourceMessageFilter : public ResourceMessageFilter { |
| public: |
| FakeResourceMessageFilter(int child_id) |
| : ResourceMessageFilter( |
| child_id, |
| PROCESS_TYPE_RENDERER, |
| NULL /* appcache_service */, |
| NULL /* blob_storage_context */, |
| NULL /* file_system_context */, |
| NULL /* service_worker_context */, |
| base::Bind(&FakeResourceMessageFilter::GetContexts, |
| base::Unretained(this))) { |
| } |
| |
| private: |
| virtual ~FakeResourceMessageFilter() {} |
| |
| void GetContexts(const ResourceHostMsg_Request& request, |
| ResourceContext** resource_context, |
| net::URLRequestContext** request_context) { |
| *resource_context = &context_; |
| *request_context = NULL; |
| } |
| |
| FakeResourceContext context_; |
| }; |
| |
| class ResourceSchedulerTest : public testing::Test { |
| protected: |
| ResourceSchedulerTest() |
| : next_request_id_(0), |
| ui_thread_(BrowserThread::UI, &message_loop_), |
| io_thread_(BrowserThread::IO, &message_loop_), |
| mock_timer_(new base::MockTimer(true, true)) { |
| scheduler_.set_timer_for_testing(scoped_ptr<base::Timer>(mock_timer_)); |
| |
| // TODO(aiolos): Remove when throttling and coalescing have both landed. |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| |
| scheduler_.OnClientCreated(kChildId, kRouteId); |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, true); |
| scheduler_.OnClientCreated(kBackgroundChildId, kBackgroundRouteId); |
| context_.set_http_server_properties(http_server_properties_.GetWeakPtr()); |
| } |
| |
| virtual ~ResourceSchedulerTest() { |
| scheduler_.OnClientDeleted(kChildId, kRouteId); |
| scheduler_.OnClientDeleted(kBackgroundChildId, kBackgroundRouteId); |
| } |
| |
| scoped_ptr<net::URLRequest> NewURLRequestWithChildAndRoute( |
| const char* url, |
| net::RequestPriority priority, |
| int child_id, |
| int route_id, |
| bool is_async) { |
| scoped_ptr<net::URLRequest> url_request( |
| context_.CreateRequest(GURL(url), priority, NULL, NULL)); |
| ResourceRequestInfoImpl* info = new ResourceRequestInfoImpl( |
| PROCESS_TYPE_RENDERER, // process_type |
| child_id, // child_id |
| route_id, // route_id |
| 0, // origin_pid |
| ++next_request_id_, // request_id |
| MSG_ROUTING_NONE, // render_frame_id |
| false, // is_main_frame |
| false, // parent_is_main_frame |
| 0, // parent_render_frame_id |
| RESOURCE_TYPE_SUB_RESOURCE, // resource_type |
| PAGE_TRANSITION_LINK, // transition_type |
| false, // should_replace_current_entry |
| false, // is_download |
| false, // is_stream |
| true, // allow_download |
| false, // has_user_gesture |
| false, // enable_load_timing |
| blink::WebReferrerPolicyDefault, // referrer_policy |
| blink::WebPageVisibilityStateVisible, // visibility_state |
| NULL, // context |
| base::WeakPtr<ResourceMessageFilter>(), // filter |
| is_async); // is_async |
| info->AssociateWithRequest(url_request.get()); |
| return url_request.Pass(); |
| } |
| |
| scoped_ptr<net::URLRequest> NewURLRequest(const char* url, |
| net::RequestPriority priority) { |
| return NewURLRequestWithChildAndRoute( |
| url, priority, kChildId, kRouteId, true); |
| } |
| |
| TestRequest* NewRequestWithRoute(const char* url, |
| net::RequestPriority priority, |
| int route_id) { |
| return NewRequestWithChildAndRoute(url, priority, route_id, kChildId); |
| } |
| |
| TestRequest* NewRequestWithChildAndRoute(const char* url, |
| net::RequestPriority priority, |
| int child_id, |
| int route_id) { |
| return GetNewTestRequest(url, priority, child_id, route_id, true); |
| } |
| |
| TestRequest* NewRequest(const char* url, net::RequestPriority priority) { |
| return NewRequestWithChildAndRoute(url, priority, kChildId, kRouteId); |
| } |
| |
| TestRequest* NewBackgroundRequest(const char* url, |
| net::RequestPriority priority) { |
| return NewRequestWithChildAndRoute( |
| url, priority, kBackgroundChildId, kBackgroundRouteId); |
| } |
| |
| TestRequest* NewSyncRequest(const char* url, net::RequestPriority priority) { |
| return NewSyncRequestWithChildAndRoute(url, priority, kChildId, kRouteId); |
| } |
| |
| TestRequest* NewBackgroundSyncRequest(const char* url, |
| net::RequestPriority priority) { |
| return NewSyncRequestWithChildAndRoute( |
| url, priority, kBackgroundChildId, kBackgroundRouteId); |
| } |
| |
| TestRequest* NewSyncRequestWithChildAndRoute(const char* url, |
| net::RequestPriority priority, |
| int child_id, |
| int route_id) { |
| return GetNewTestRequest(url, priority, child_id, route_id, false); |
| } |
| |
| TestRequest* GetNewTestRequest(const char* url, |
| net::RequestPriority priority, |
| int child_id, |
| int route_id, |
| bool is_async) { |
| scoped_ptr<net::URLRequest> url_request(NewURLRequestWithChildAndRoute( |
| url, priority, child_id, route_id, is_async)); |
| scoped_ptr<ResourceThrottle> throttle( |
| scheduler_.ScheduleRequest(child_id, route_id, url_request.get())); |
| TestRequest* request = new TestRequest(throttle.Pass(), url_request.Pass()); |
| request->Start(); |
| return request; |
| } |
| |
| |
| void ChangeRequestPriority(TestRequest* request, |
| net::RequestPriority new_priority, |
| int intra_priority = 0) { |
| scoped_refptr<FakeResourceMessageFilter> filter( |
| new FakeResourceMessageFilter(kChildId)); |
| const ResourceRequestInfoImpl* info = ResourceRequestInfoImpl::ForRequest( |
| request->url_request()); |
| const GlobalRequestID& id = info->GetGlobalRequestID(); |
| ResourceHostMsg_DidChangePriority msg(id.request_id, new_priority, |
| intra_priority); |
| rdh_.OnMessageReceived(msg, filter.get()); |
| } |
| |
| void FireCoalescingTimer() { |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| mock_timer_->Fire(); |
| } |
| |
| int next_request_id_; |
| base::MessageLoopForIO message_loop_; |
| BrowserThreadImpl ui_thread_; |
| BrowserThreadImpl io_thread_; |
| ResourceDispatcherHostImpl rdh_; |
| ResourceScheduler scheduler_; |
| base::MockTimer* mock_timer_; |
| net::HttpServerPropertiesImpl http_server_properties_; |
| net::TestURLRequestContext context_; |
| }; |
| |
| TEST_F(ResourceSchedulerTest, OneIsolatedLowRequest) { |
| scoped_ptr<TestRequest> request(NewRequest("http://host/1", net::LOWEST)); |
| EXPECT_TRUE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, OneLowLoadsUntilIdle) { |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST)); |
| EXPECT_TRUE(high->started()); |
| EXPECT_TRUE(low->started()); |
| EXPECT_FALSE(low2->started()); |
| high.reset(); |
| EXPECT_TRUE(low2->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInserted) { |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST)); |
| EXPECT_TRUE(high->started()); |
| EXPECT_TRUE(low->started()); |
| EXPECT_FALSE(low2->started()); |
| scheduler_.OnWillInsertBody(kChildId, kRouteId); |
| EXPECT_TRUE(low2->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) { |
| http_server_properties_.SetSupportsSpdy( |
| net::HostPortPair("spdyhost", 443), true); |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low_spdy( |
| NewRequest("https://spdyhost/low", net::LOWEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST)); |
| EXPECT_TRUE(high->started()); |
| EXPECT_TRUE(low_spdy->started()); |
| EXPECT_TRUE(low->started()); |
| EXPECT_FALSE(low2->started()); |
| scheduler_.OnWillInsertBody(kChildId, kRouteId); |
| EXPECT_TRUE(low2->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, NavigationResetsState) { |
| scheduler_.OnWillInsertBody(kChildId, kRouteId); |
| scheduler_.OnNavigate(kChildId, kRouteId); |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST)); |
| EXPECT_TRUE(high->started()); |
| EXPECT_TRUE(low->started()); |
| EXPECT_FALSE(low2->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, BackgroundRequestStartsImmediately) { |
| const int route_id = 0; // Indicates a background request. |
| scoped_ptr<TestRequest> request(NewRequestWithRoute("http://host/1", |
| net::LOWEST, route_id)); |
| EXPECT_TRUE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, StartMultipleLowRequestsWhenIdle) { |
| scoped_ptr<TestRequest> high1(NewRequest("http://host/high1", net::HIGHEST)); |
| scoped_ptr<TestRequest> high2(NewRequest("http://host/high2", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST)); |
| EXPECT_TRUE(high1->started()); |
| EXPECT_TRUE(high2->started()); |
| EXPECT_TRUE(low->started()); |
| EXPECT_FALSE(low2->started()); |
| high1.reset(); |
| EXPECT_FALSE(low2->started()); |
| high2.reset(); |
| EXPECT_TRUE(low2->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CancelOtherRequestsWhileResuming) { |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low1(NewRequest("http://host/low1", net::LOWEST)); |
| |
| scoped_ptr<net::URLRequest> url_request( |
| NewURLRequest("http://host/low2", net::LOWEST)); |
| scoped_ptr<ResourceThrottle> throttle( |
| scheduler_.ScheduleRequest(kChildId, kRouteId, url_request.get())); |
| scoped_ptr<CancelingTestRequest> low2(new CancelingTestRequest( |
| throttle.Pass(), url_request.Pass())); |
| low2->Start(); |
| |
| scoped_ptr<TestRequest> low3(NewRequest("http://host/low3", net::LOWEST)); |
| low2->set_request_to_cancel(low3.Pass()); |
| scoped_ptr<TestRequest> low4(NewRequest("http://host/low4", net::LOWEST)); |
| |
| EXPECT_TRUE(high->started()); |
| EXPECT_FALSE(low2->started()); |
| high.reset(); |
| EXPECT_TRUE(low1->started()); |
| EXPECT_TRUE(low2->started()); |
| EXPECT_TRUE(low4->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) { |
| // We only load low priority resources if there's a body. |
| scheduler_.OnWillInsertBody(kChildId, kRouteId); |
| |
| // Throw in one high priority request to make sure that's not a factor. |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| EXPECT_TRUE(high->started()); |
| |
| const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc. |
| const int kMaxNumDelayableRequestsPerHost = 6; |
| ScopedVector<TestRequest> lows_singlehost; |
| // Queue up to the per-host limit (we subtract the current high-pri request). |
| for (int i = 0; i < kMaxNumDelayableRequestsPerHost - 1; ++i) { |
| string url = "http://host/low" + base::IntToString(i); |
| lows_singlehost.push_back(NewRequest(url.c_str(), net::LOWEST)); |
| EXPECT_TRUE(lows_singlehost[i]->started()); |
| } |
| |
| scoped_ptr<TestRequest> second_last_singlehost(NewRequest("http://host/last", |
| net::LOWEST)); |
| scoped_ptr<TestRequest> last_singlehost(NewRequest("http://host/s_last", |
| net::LOWEST)); |
| |
| EXPECT_FALSE(second_last_singlehost->started()); |
| high.reset(); |
| EXPECT_TRUE(second_last_singlehost->started()); |
| EXPECT_FALSE(last_singlehost->started()); |
| lows_singlehost.erase(lows_singlehost.begin()); |
| EXPECT_TRUE(last_singlehost->started()); |
| |
| // Queue more requests from different hosts until we reach the total limit. |
| int expected_slots_left = |
| kMaxNumDelayableRequestsPerClient - kMaxNumDelayableRequestsPerHost; |
| EXPECT_GT(expected_slots_left, 0); |
| ScopedVector<TestRequest> lows_differenthosts; |
| for (int i = 0; i < expected_slots_left; ++i) { |
| string url = "http://host" + base::IntToString(i) + "/low"; |
| lows_differenthosts.push_back(NewRequest(url.c_str(), net::LOWEST)); |
| EXPECT_TRUE(lows_differenthosts[i]->started()); |
| } |
| |
| scoped_ptr<TestRequest> last_differenthost(NewRequest("http://host_new/last", |
| net::LOWEST)); |
| EXPECT_FALSE(last_differenthost->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, RaisePriorityAndStart) { |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/req", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::LOWEST)); |
| EXPECT_FALSE(request->started()); |
| |
| ChangeRequestPriority(request.get(), net::HIGHEST); |
| EXPECT_TRUE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, RaisePriorityInQueue) { |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::IDLE)); |
| scoped_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE)); |
| EXPECT_FALSE(request->started()); |
| EXPECT_FALSE(idle->started()); |
| |
| ChangeRequestPriority(request.get(), net::LOWEST); |
| EXPECT_FALSE(request->started()); |
| EXPECT_FALSE(idle->started()); |
| |
| const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc. |
| ScopedVector<TestRequest> lows; |
| for (int i = 0; i < kMaxNumDelayableRequestsPerClient - 1; ++i) { |
| string url = "http://host/low" + base::IntToString(i); |
| lows.push_back(NewRequest(url.c_str(), net::LOWEST)); |
| } |
| |
| scheduler_.OnWillInsertBody(kChildId, kRouteId); |
| EXPECT_TRUE(request->started()); |
| EXPECT_FALSE(idle->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, LowerPriority) { |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::LOWEST)); |
| scoped_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE)); |
| EXPECT_FALSE(request->started()); |
| EXPECT_FALSE(idle->started()); |
| |
| ChangeRequestPriority(request.get(), net::IDLE); |
| EXPECT_FALSE(request->started()); |
| EXPECT_FALSE(idle->started()); |
| |
| const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc. |
| // 2 fewer filler requests: 1 for the "low" dummy at the start, and 1 for the |
| // one at the end, which will be tested. |
| const int kNumFillerRequests = kMaxNumDelayableRequestsPerClient - 2; |
| ScopedVector<TestRequest> lows; |
| for (int i = 0; i < kNumFillerRequests; ++i) { |
| string url = "http://host" + base::IntToString(i) + "/low"; |
| lows.push_back(NewRequest(url.c_str(), net::LOWEST)); |
| } |
| |
| scheduler_.OnWillInsertBody(kChildId, kRouteId); |
| EXPECT_FALSE(request->started()); |
| EXPECT_TRUE(idle->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ReprioritizedRequestGoesToBackOfQueue) { |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::LOWEST)); |
| scoped_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE)); |
| EXPECT_FALSE(request->started()); |
| EXPECT_FALSE(idle->started()); |
| |
| const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc. |
| ScopedVector<TestRequest> lows; |
| for (int i = 0; i < kMaxNumDelayableRequestsPerClient; ++i) { |
| string url = "http://host/low" + base::IntToString(i); |
| lows.push_back(NewRequest(url.c_str(), net::LOWEST)); |
| } |
| |
| ChangeRequestPriority(request.get(), net::IDLE); |
| EXPECT_FALSE(request->started()); |
| EXPECT_FALSE(idle->started()); |
| |
| ChangeRequestPriority(request.get(), net::LOWEST); |
| EXPECT_FALSE(request->started()); |
| EXPECT_FALSE(idle->started()); |
| |
| scheduler_.OnWillInsertBody(kChildId, kRouteId); |
| EXPECT_FALSE(request->started()); |
| EXPECT_FALSE(idle->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, HigherIntraPriorityGoesToFrontOfQueue) { |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| |
| const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc. |
| ScopedVector<TestRequest> lows; |
| for (int i = 0; i < kMaxNumDelayableRequestsPerClient; ++i) { |
| string url = "http://host/low" + base::IntToString(i); |
| lows.push_back(NewRequest(url.c_str(), net::IDLE)); |
| } |
| |
| scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::IDLE)); |
| EXPECT_FALSE(request->started()); |
| |
| ChangeRequestPriority(request.get(), net::IDLE, 1); |
| EXPECT_FALSE(request->started()); |
| |
| scheduler_.OnWillInsertBody(kChildId, kRouteId); |
| EXPECT_TRUE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, NonHTTPSchedulesImmediately) { |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request( |
| NewRequest("chrome-extension://req", net::LOWEST)); |
| EXPECT_TRUE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ActiveLoadingSyncSchedulesImmediately) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request( |
| NewSyncRequest("http://host/req", net::LOWEST)); |
| EXPECT_TRUE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, UnthrottledSyncSchedulesImmediately) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request( |
| NewBackgroundSyncRequest("http://host/req", net::LOWEST)); |
| EXPECT_TRUE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, SpdyProxySchedulesImmediately) { |
| scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::IDLE)); |
| EXPECT_FALSE(request->started()); |
| |
| scheduler_.OnReceivedSpdyProxiedHttpResponse(kChildId, kRouteId); |
| EXPECT_TRUE(request->started()); |
| |
| scoped_ptr<TestRequest> after(NewRequest("http://host/after", net::IDLE)); |
| EXPECT_TRUE(after->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) { |
| scheduler_.OnWillInsertBody(kChildId, kRouteId); |
| const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc. |
| |
| scoped_ptr<TestRequest> low1_spdy( |
| NewRequest("http://spdyhost1:8080/low", net::LOWEST)); |
| // Cancel a request after we learn the server supports SPDY. |
| ScopedVector<TestRequest> lows; |
| for (int i = 0; i < kMaxNumDelayableRequestsPerClient - 1; ++i) { |
| string url = "http://host" + base::IntToString(i) + "/low"; |
| lows.push_back(NewRequest(url.c_str(), net::LOWEST)); |
| } |
| scoped_ptr<TestRequest> low1(NewRequest("http://host/low", net::LOWEST)); |
| EXPECT_FALSE(low1->started()); |
| http_server_properties_.SetSupportsSpdy( |
| net::HostPortPair("spdyhost1", 8080), true); |
| low1_spdy.reset(); |
| EXPECT_TRUE(low1->started()); |
| |
| low1.reset(); |
| scoped_ptr<TestRequest> low2_spdy( |
| NewRequest("http://spdyhost2:8080/low", net::IDLE)); |
| // Reprioritize a request after we learn the server supports SPDY. |
| EXPECT_TRUE(low2_spdy->started()); |
| http_server_properties_.SetSupportsSpdy( |
| net::HostPortPair("spdyhost2", 8080), true); |
| ChangeRequestPriority(low2_spdy.get(), net::LOWEST); |
| scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST)); |
| EXPECT_TRUE(low2->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ThrottledClientCreation) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| EXPECT_TRUE(scheduler_.should_throttle()); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ActiveClientThrottleUpdateOnLoadingChange) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalesceBackgroundClientOnLoadCompletion) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| } |
| |
| TEST_F(ResourceSchedulerTest, UnthrottleBackgroundClientOnLoadingStarted) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, false); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| } |
| |
| TEST_F(ResourceSchedulerTest, OneRequestPerThrottledClient) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> request( |
| NewBackgroundRequest("http://host/req", net::IDLE)); |
| |
| EXPECT_TRUE(high->started()); |
| EXPECT_FALSE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, UnthrottleNewlyVisibleClient) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> request( |
| NewBackgroundRequest("http://host/req", net::IDLE)); |
| EXPECT_FALSE(request->started()); |
| |
| scheduler_.OnVisibilityChanged(kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, UnthrottleNewlyAudibleClient) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> request( |
| NewBackgroundRequest("http://host/req", net::IDLE)); |
| EXPECT_FALSE(request->started()); |
| |
| scheduler_.OnAudibilityChanged(kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(request->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, VisibleClientStillUnthrottledOnAudabilityChange) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, true); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, false); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| } |
| |
| TEST_F(ResourceSchedulerTest, AudibleClientStillUnthrottledOnVisabilityChange) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, true); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, true); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ThrottledClientStartsNextHighestPriorityRequest) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scoped_ptr<TestRequest> request( |
| NewBackgroundRequest("http://host/req", net::IDLE)); |
| // Lower priority request started first to test request prioritizaton. |
| scoped_ptr<TestRequest> low( |
| NewBackgroundRequest("http://host/high", net::IDLE)); |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| |
| EXPECT_FALSE(low->started()); |
| EXPECT_FALSE(high->started()); |
| |
| // request->CancelRequest(); |
| request->Cancel(); |
| EXPECT_TRUE(high->started()); |
| EXPECT_FALSE(low->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ThrottledSpdyProxySchedulesImmediately) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> request( |
| NewBackgroundRequest("http://host/req", net::IDLE)); |
| |
| EXPECT_FALSE(request->started()); |
| |
| scheduler_.OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId, |
| kBackgroundRouteId); |
| EXPECT_TRUE(request->started()); |
| |
| scoped_ptr<TestRequest> after( |
| NewBackgroundRequest("http://host/after", net::IDLE)); |
| EXPECT_TRUE(after->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalescedClientIssuesNoRequests) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> request( |
| NewBackgroundRequest("http://host/req", net::IDLE)); |
| |
| EXPECT_FALSE(high->started()); |
| EXPECT_FALSE(request->started()); |
| |
| scheduler_.OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId, |
| kBackgroundRouteId); |
| EXPECT_FALSE(high->started()); |
| |
| scoped_ptr<TestRequest> after( |
| NewBackgroundRequest("http://host/after", net::HIGHEST)); |
| EXPECT_FALSE(after->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalescedSpdyProxyWaits) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> request( |
| NewBackgroundRequest("http://host/req", net::IDLE)); |
| |
| EXPECT_FALSE(request->started()); |
| |
| scheduler_.OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId, |
| kBackgroundRouteId); |
| EXPECT_FALSE(request->started()); |
| |
| scoped_ptr<TestRequest> after( |
| NewBackgroundRequest("http://host/after", net::IDLE)); |
| EXPECT_FALSE(after->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ThrottledNonHTTPSchedulesImmediately) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request( |
| NewBackgroundRequest("chrome-extension://req", net::LOWEST)); |
| EXPECT_TRUE(request->started()); |
| EXPECT_FALSE(low->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalescedNonHTTPSchedulesImmediately) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request( |
| NewBackgroundRequest("chrome-extension://req", net::LOWEST)); |
| EXPECT_TRUE(request->started()); |
| EXPECT_FALSE(low->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ThrottledSyncSchedulesImmediately) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request( |
| NewBackgroundSyncRequest("http://host/req", net::LOWEST)); |
| EXPECT_TRUE(request->started()); |
| EXPECT_FALSE(low->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalescedSyncSchedulesImmediately) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| // Dummies to enforce scheduling. |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| |
| scoped_ptr<TestRequest> request( |
| NewBackgroundSyncRequest("http://host/req", net::LOWEST)); |
| EXPECT_TRUE(request->started()); |
| EXPECT_FALSE(low->started()); |
| EXPECT_FALSE(high->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, AllBackgroundClientsUnthrottle) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| } |
| |
| TEST_F(ResourceSchedulerTest, |
| UnloadedClientVisibilityChangedCorrectlyUnthrottles) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| |
| // 1 visible, 3 hidden |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 2 visible, 2 hidden |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible, 3 hidden |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, |
| UnloadedClientAudibilityChangedCorrectlyUnthrottles) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, true); |
| |
| // 1 audible, 3 hidden |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 2 audible, 2 hidden |
| scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 audible, 3 hidden |
| scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, |
| LoadedClientVisibilityChangedCorrectlyUnthrottles) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| // 1 visible, 3 hidden |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 2 visible, 2 hidden |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible, 3 hidden |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, |
| LoadedClientAudibilityChangedCorrectlyUnthrottles) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, true); |
| // 1 audible, 3 hidden |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 2 audible, 2 hidden |
| scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 audible, 3 hidden |
| scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, UnloadedClientBecomesHiddenCorrectlyUnthrottles) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| |
| // 2 visible, 2 hidden |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible, 3 hidden |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 0 visible, 4 hidden |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible, 3 hidden |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, UnloadedClientBecomesSilentCorrectlyUnthrottles) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, true); |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, true); |
| // 2 audible, 2 hidden |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 audible, 3 hidden |
| scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 0 audible, 4 hidden |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, false); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 audible, 3 hidden |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, LoadedClientBecomesHiddenCorrectlyThrottles) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true); |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true); |
| // 2 visible, 2 hidden |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible, 3 hidden |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 0 visible, 4 hidden |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible, 3 hidden |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, LoadedClientBecomesSilentCorrectlyThrottles) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true); |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, true); |
| scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, true); |
| // 2 audible, 2 hidden |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 audible, 3 hidden |
| scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 0 audible, 4 hidden |
| scheduler_.OnAudibilityChanged(kChildId, kRouteId, false); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 audible, 3 hidden |
| scheduler_.OnAudibilityChanged(kChildId2, kRouteId2, true); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, HiddenLoadedChangesCorrectlyStayThrottled) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| |
| // 1 visible and 2 hidden loading, 1 visible loaded |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible and 1 hidden loading, 1 visible and 1 hidden loaded |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible loading, 1 visible and 2 hidden loaded |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible and 1 hidden loading, 1 visible and 1 hidden loaded |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, PartialVisibleClientLoadedDoesNotUnthrottle) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true); |
| |
| // 2 visible loading, 1 hidden loading, 1 hidden loaded |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 2 visible loading, 1 hidden loading, 1 hidden loaded |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, FullVisibleLoadedCorrectlyUnthrottle) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true); |
| |
| // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| scheduler_.OnLoadingStateChanged(kChildId2, kRouteId2, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| |
| EXPECT_TRUE(high->started()); |
| EXPECT_FALSE(low->started()); |
| |
| // 2 visible loaded, 1 hidden loading, 1 hidden loaded |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| // kBackgroundClientId unthrottling should unthrottle it's request. |
| EXPECT_TRUE(low->started()); |
| |
| // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, |
| ActiveAndLoadingClientDeletedCorrectlyUnthrottle) { |
| // TODO(aiolos): remove when throttling and coalescing have both landed |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| false /* should_coalesce */); |
| scheduler_.OnClientCreated(kChildId2, kRouteId2); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| scheduler_.OnVisibilityChanged(kChildId2, kRouteId2, true); |
| |
| // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId2, kRouteId2)); |
| |
| // 1 visible loaded, 1 hidden loading, 1 hidden loaded |
| scheduler_.OnClientDeleted(kChildId2, kRouteId2); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, false); |
| EXPECT_FALSE(scheduler_.active_clients_loaded()); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalescedClientCreationStartsTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ActiveLoadingClientLoadedAndHiddenStartsTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, ActiveLoadingClientHiddenAndLoadedStartsTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::THROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnVisibilityChanged(kChildId, kRouteId, false); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kChildId, kRouteId)); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalescedClientBecomesAudibleStopsTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnAudibilityChanged(kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, LastCoalescedClientDeletionStopsTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnClientDeleted(kBackgroundChildId, kBackgroundRouteId); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| |
| // To avoid errors on test tear down. |
| scheduler_.OnClientCreated(kBackgroundChildId, kBackgroundRouteId); |
| } |
| |
| TEST_F(ResourceSchedulerTest, LastCoalescedClientStartsLoadingStopsTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, false); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, false); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| |
| // This is needed to avoid errors on test tear down. |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, LastCoalescedClientBecomesVisibleStopsTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnClientCreated(kBackgroundChildId2, kBackgroundRouteId2); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId2, |
| kBackgroundRouteId2)); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnVisibilityChanged(kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnVisibilityChanged( |
| kBackgroundChildId2, kBackgroundRouteId2, true); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| |
| // To avoid errors on test tear down. |
| scheduler_.OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2); |
| } |
| |
| TEST_F(ResourceSchedulerTest, |
| CoalescedClientBecomesLoadingAndVisibleStopsTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, false); |
| EXPECT_EQ(ResourceScheduler::UNTHROTTLED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| |
| scheduler_.OnVisibilityChanged(kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_FALSE(mock_timer_->IsRunning()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalescedRequestsIssueOnTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| EXPECT_FALSE(high->started()); |
| EXPECT_FALSE(low->started()); |
| |
| FireCoalescingTimer(); |
| |
| EXPECT_TRUE(high->started()); |
| EXPECT_TRUE(low->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalescedRequestsUnthrottleCorrectlyOnTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> high2( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> high3( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> high4( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| scoped_ptr<TestRequest> low( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| scoped_ptr<TestRequest> low2( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| scoped_ptr<TestRequest> low3( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| scoped_ptr<TestRequest> low4( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| |
| http_server_properties_.SetSupportsSpdy(net::HostPortPair("spdyhost", 443), |
| true); |
| scoped_ptr<TestRequest> low_spdy( |
| NewBackgroundRequest("https://spdyhost/low", net::LOW)); |
| scoped_ptr<TestRequest> sync_request( |
| NewBackgroundSyncRequest("http://host/req", net::LOW)); |
| scoped_ptr<TestRequest> non_http_request( |
| NewBackgroundRequest("chrome-extension://req", net::LOW)); |
| |
| // Sync requests should issue immediately. |
| EXPECT_TRUE(sync_request->started()); |
| // Non-http(s) requests should issue immediately. |
| EXPECT_TRUE(non_http_request->started()); |
| // Nothing else should issue without a timer fire. |
| EXPECT_FALSE(high->started()); |
| EXPECT_FALSE(high2->started()); |
| EXPECT_FALSE(high3->started()); |
| EXPECT_FALSE(high4->started()); |
| EXPECT_FALSE(low->started()); |
| EXPECT_FALSE(low2->started()); |
| EXPECT_FALSE(low3->started()); |
| EXPECT_FALSE(low4->started()); |
| EXPECT_FALSE(low_spdy->started()); |
| |
| FireCoalescingTimer(); |
| |
| // All high priority requests should issue. |
| EXPECT_TRUE(high->started()); |
| EXPECT_TRUE(high2->started()); |
| EXPECT_TRUE(high3->started()); |
| EXPECT_TRUE(high4->started()); |
| // There should only be one net::LOWEST priority request issued with |
| // non-delayable requests in flight. |
| EXPECT_TRUE(low->started()); |
| EXPECT_FALSE(low2->started()); |
| EXPECT_FALSE(low3->started()); |
| EXPECT_FALSE(low4->started()); |
| // Spdy-Enable requests should issue regardless of priority. |
| EXPECT_TRUE(low_spdy->started()); |
| } |
| |
| TEST_F(ResourceSchedulerTest, CoalescedRequestsWaitForNextTimer) { |
| scheduler_.SetThrottleOptionsForTesting(true /* should_throttle */, |
| true /* should_coalesce */); |
| scheduler_.OnLoadingStateChanged(kChildId, kRouteId, true); |
| scheduler_.OnLoadingStateChanged( |
| kBackgroundChildId, kBackgroundRouteId, true); |
| |
| EXPECT_EQ(ResourceScheduler::COALESCED, |
| scheduler_.GetClientStateForTesting(kBackgroundChildId, |
| kBackgroundRouteId)); |
| EXPECT_TRUE(scheduler_.active_clients_loaded()); |
| |
| scoped_ptr<TestRequest> high( |
| NewBackgroundRequest("http://host/high", net::HIGHEST)); |
| EXPECT_FALSE(high->started()); |
| |
| FireCoalescingTimer(); |
| |
| scoped_ptr<TestRequest> high2( |
| NewBackgroundRequest("http://host/high2", net::HIGHEST)); |
| scoped_ptr<TestRequest> low( |
| NewBackgroundRequest("http://host/low", net::LOWEST)); |
| |
| EXPECT_TRUE(high->started()); |
| EXPECT_FALSE(high2->started()); |
| EXPECT_FALSE(low->started()); |
| |
| FireCoalescingTimer(); |
| |
| EXPECT_TRUE(high->started()); |
| EXPECT_TRUE(high2->started()); |
| EXPECT_TRUE(low->started()); |
| } |
| |
| } // unnamed namespace |
| |
| } // namespace content |