OLD | NEW |
| (Empty) |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "components/offline_pages/background/request_coordinator.h" | |
6 | |
7 #include <memory> | |
8 #include <string> | |
9 #include <utility> | |
10 #include <vector> | |
11 | |
12 #include "base/bind.h" | |
13 #include "base/location.h" | |
14 #include "base/logging.h" | |
15 #include "base/synchronization/waitable_event.h" | |
16 #include "base/sys_info.h" | |
17 #include "base/test/histogram_tester.h" | |
18 #include "base/test/scoped_feature_list.h" | |
19 #include "base/test/test_mock_time_task_runner.h" | |
20 #include "base/threading/thread_task_runner_handle.h" | |
21 #include "base/time/time.h" | |
22 #include "components/offline_pages/background/device_conditions.h" | |
23 #include "components/offline_pages/background/network_quality_provider_stub.h" | |
24 #include "components/offline_pages/background/offliner.h" | |
25 #include "components/offline_pages/background/offliner_factory.h" | |
26 #include "components/offline_pages/background/offliner_factory_stub.h" | |
27 #include "components/offline_pages/background/offliner_policy.h" | |
28 #include "components/offline_pages/background/offliner_stub.h" | |
29 #include "components/offline_pages/background/request_queue.h" | |
30 #include "components/offline_pages/background/request_queue_in_memory_store.h" | |
31 #include "components/offline_pages/background/save_page_request.h" | |
32 #include "components/offline_pages/background/scheduler.h" | |
33 #include "components/offline_pages/background/scheduler_stub.h" | |
34 #include "components/offline_pages/offline_page_feature.h" | |
35 #include "testing/gtest/include/gtest/gtest.h" | |
36 | |
37 namespace offline_pages { | |
38 | |
39 namespace { | |
40 // put test constants here | |
41 const GURL kUrl1("http://universe.com/everything"); | |
42 const GURL kUrl2("http://universe.com/toinfinityandbeyond"); | |
43 const std::string kClientNamespace("bookmark"); | |
44 const std::string kId1("42"); | |
45 const std::string kId2("life*universe+everything"); | |
46 const ClientId kClientId1(kClientNamespace, kId1); | |
47 const ClientId kClientId2(kClientNamespace, kId2); | |
48 const int kRequestId1(1); | |
49 const int kRequestId2(2); | |
50 const long kTestTimeBudgetSeconds = 200; | |
51 const int kBatteryPercentageHigh = 75; | |
52 const int kMaxCompletedTries = 3; | |
53 const bool kPowerRequired = true; | |
54 const bool kUserRequested = true; | |
55 const int kAttemptCount = 1; | |
56 } // namespace | |
57 | |
58 class ObserverStub : public RequestCoordinator::Observer { | |
59 public: | |
60 ObserverStub() | |
61 : added_called_(false), | |
62 completed_called_(false), | |
63 changed_called_(false), | |
64 last_status_(RequestCoordinator::BackgroundSavePageResult::SUCCESS), | |
65 state_(SavePageRequest::RequestState::OFFLINING) {} | |
66 | |
67 void Clear() { | |
68 added_called_ = false; | |
69 completed_called_ = false; | |
70 changed_called_ = false; | |
71 state_ = SavePageRequest::RequestState::OFFLINING; | |
72 last_status_ = RequestCoordinator::BackgroundSavePageResult::SUCCESS; | |
73 } | |
74 | |
75 void OnAdded(const SavePageRequest& request) override { | |
76 added_called_ = true; | |
77 } | |
78 | |
79 void OnCompleted( | |
80 const SavePageRequest& request, | |
81 RequestCoordinator::BackgroundSavePageResult status) override { | |
82 completed_called_ = true; | |
83 last_status_ = status; | |
84 } | |
85 | |
86 void OnChanged(const SavePageRequest& request) override { | |
87 changed_called_ = true; | |
88 state_ = request.request_state(); | |
89 } | |
90 | |
91 bool added_called() { return added_called_; } | |
92 bool completed_called() { return completed_called_; } | |
93 bool changed_called() { return changed_called_; } | |
94 RequestCoordinator::BackgroundSavePageResult last_status() { | |
95 return last_status_; | |
96 } | |
97 SavePageRequest::RequestState state() { return state_; } | |
98 | |
99 private: | |
100 bool added_called_; | |
101 bool completed_called_; | |
102 bool changed_called_; | |
103 RequestCoordinator::BackgroundSavePageResult last_status_; | |
104 SavePageRequest::RequestState state_; | |
105 }; | |
106 | |
107 class RequestCoordinatorTest | |
108 : public testing::Test { | |
109 public: | |
110 RequestCoordinatorTest(); | |
111 ~RequestCoordinatorTest() override; | |
112 | |
113 void SetUp() override; | |
114 | |
115 void PumpLoop(); | |
116 | |
117 RequestCoordinator* coordinator() { | |
118 return coordinator_.get(); | |
119 } | |
120 | |
121 bool is_busy() { | |
122 return coordinator_->is_busy(); | |
123 } | |
124 | |
125 bool is_starting() { return coordinator_->is_starting(); } | |
126 | |
127 // Empty callback function. | |
128 void ImmediateScheduleCallbackFunction(bool result) { | |
129 immediate_schedule_callback_called_ = true; | |
130 immediate_schedule_callback_result_ = result; | |
131 } | |
132 | |
133 // Callback function which releases a wait for it. | |
134 void WaitingCallbackFunction(bool result) { | |
135 waiter_.Signal(); | |
136 } | |
137 | |
138 net::NetworkChangeNotifier::ConnectionType GetConnectionType() { | |
139 return coordinator()->GetConnectionType(); | |
140 } | |
141 | |
142 // Callback for Add requests. | |
143 void AddRequestDone(AddRequestResult result, const SavePageRequest& request); | |
144 | |
145 // Callback for getting requests. | |
146 void GetRequestsDone(GetRequestsResult result, | |
147 std::vector<std::unique_ptr<SavePageRequest>> requests); | |
148 | |
149 // Callback for removing requests. | |
150 void RemoveRequestsDone(const MultipleItemStatuses& results); | |
151 | |
152 // Callback for getting request statuses. | |
153 void GetQueuedRequestsDone( | |
154 std::vector<std::unique_ptr<SavePageRequest>> requests); | |
155 | |
156 void SetupForOfflinerDoneCallbackTest( | |
157 offline_pages::SavePageRequest* request); | |
158 | |
159 void SendOfflinerDoneCallback(const SavePageRequest& request, | |
160 Offliner::RequestStatus status); | |
161 | |
162 GetRequestsResult last_get_requests_result() const { | |
163 return last_get_requests_result_; | |
164 } | |
165 | |
166 const std::vector<std::unique_ptr<SavePageRequest>>& last_requests() const { | |
167 return last_requests_; | |
168 } | |
169 | |
170 const MultipleItemStatuses& last_remove_results() const { | |
171 return last_remove_results_; | |
172 } | |
173 | |
174 void DisableLoading() { | |
175 offliner_->disable_loading(); | |
176 } | |
177 | |
178 void EnableOfflinerCallback(bool enable) { | |
179 offliner_->enable_callback(enable); | |
180 } | |
181 | |
182 void SetNetworkConditionsForTest( | |
183 net::NetworkChangeNotifier::ConnectionType connection) { | |
184 coordinator()->SetNetworkConditionsForTest(connection); | |
185 } | |
186 | |
187 void SetEffectiveConnectionTypeForTest(net::EffectiveConnectionType type) { | |
188 network_quality_estimator_->SetEffectiveConnectionTypeForTest(type); | |
189 } | |
190 | |
191 void SetNetworkConnected(bool connected) { | |
192 if (connected) { | |
193 SetNetworkConditionsForTest( | |
194 net::NetworkChangeNotifier::ConnectionType::CONNECTION_3G); | |
195 SetEffectiveConnectionTypeForTest( | |
196 net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G); | |
197 } else { | |
198 SetNetworkConditionsForTest( | |
199 net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE); | |
200 SetEffectiveConnectionTypeForTest( | |
201 net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_OFFLINE); | |
202 } | |
203 } | |
204 | |
205 void CallConnectionTypeObserver() { | |
206 if (coordinator()->connection_notifier_) { | |
207 coordinator()->connection_notifier_->OnConnectionTypeChanged( | |
208 GetConnectionType()); | |
209 } | |
210 } | |
211 | |
212 void SetIsLowEndDeviceForTest(bool is_low_end_device) { | |
213 coordinator()->is_low_end_device_ = is_low_end_device; | |
214 } | |
215 | |
216 void SetProcessingStateForTest( | |
217 RequestCoordinator::ProcessingWindowState processing_state) { | |
218 coordinator()->processing_state_ = processing_state; | |
219 } | |
220 | |
221 void SetOperationStartTimeForTest(base::Time start_time) { | |
222 coordinator()->operation_start_time_ = start_time; | |
223 } | |
224 | |
225 void ScheduleForTest() { coordinator_->ScheduleAsNeeded(); } | |
226 | |
227 void CallRequestNotPicked(bool non_user_requested_tasks_remaining, | |
228 bool disabled_tasks_remaining) { | |
229 if (disabled_tasks_remaining) | |
230 coordinator_->disabled_requests_.insert(kRequestId1); | |
231 else | |
232 coordinator_->disabled_requests_.clear(); | |
233 | |
234 coordinator_->RequestNotPicked(non_user_requested_tasks_remaining, false); | |
235 } | |
236 | |
237 void SetDeviceConditionsForTest(DeviceConditions device_conditions) { | |
238 coordinator_->SetDeviceConditionsForTest(device_conditions); | |
239 } | |
240 | |
241 void WaitForCallback() { | |
242 waiter_.Wait(); | |
243 } | |
244 | |
245 void AdvanceClockBy(base::TimeDelta delta) { | |
246 task_runner_->FastForwardBy(delta); | |
247 } | |
248 | |
249 SavePageRequest AddRequest1(); | |
250 | |
251 SavePageRequest AddRequest2(); | |
252 | |
253 Offliner::RequestStatus last_offlining_status() const { | |
254 return coordinator_->last_offlining_status_; | |
255 } | |
256 | |
257 bool OfflinerWasCanceled() const { return offliner_->cancel_called(); } | |
258 | |
259 ObserverStub observer() { return observer_; } | |
260 | |
261 DeviceConditions device_conditions() { return device_conditions_; } | |
262 | |
263 base::Callback<void(bool)> immediate_callback() { | |
264 return immediate_callback_; | |
265 } | |
266 | |
267 base::Callback<void(bool)> waiting_callback() { return waiting_callback_; } | |
268 bool immediate_schedule_callback_called() const { | |
269 return immediate_schedule_callback_called_; | |
270 } | |
271 | |
272 bool immediate_schedule_callback_result() const { | |
273 return immediate_schedule_callback_result_; | |
274 } | |
275 | |
276 const base::HistogramTester& histograms() const { return histogram_tester_; } | |
277 | |
278 private: | |
279 GetRequestsResult last_get_requests_result_; | |
280 MultipleItemStatuses last_remove_results_; | |
281 std::vector<std::unique_ptr<SavePageRequest>> last_requests_; | |
282 scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; | |
283 base::ThreadTaskRunnerHandle task_runner_handle_; | |
284 std::unique_ptr<NetworkQualityProviderStub> network_quality_estimator_; | |
285 std::unique_ptr<RequestCoordinator> coordinator_; | |
286 OfflinerStub* offliner_; | |
287 base::WaitableEvent waiter_; | |
288 ObserverStub observer_; | |
289 bool immediate_schedule_callback_called_; | |
290 bool immediate_schedule_callback_result_; | |
291 DeviceConditions device_conditions_; | |
292 base::Callback<void(bool)> immediate_callback_; | |
293 base::Callback<void(bool)> waiting_callback_; | |
294 base::HistogramTester histogram_tester_; | |
295 }; | |
296 | |
297 RequestCoordinatorTest::RequestCoordinatorTest() | |
298 : last_get_requests_result_(GetRequestsResult::STORE_FAILURE), | |
299 task_runner_(new base::TestMockTimeTaskRunner), | |
300 task_runner_handle_(task_runner_), | |
301 offliner_(nullptr), | |
302 waiter_(base::WaitableEvent::ResetPolicy::MANUAL, | |
303 base::WaitableEvent::InitialState::NOT_SIGNALED), | |
304 immediate_schedule_callback_called_(false), | |
305 immediate_schedule_callback_result_(false), | |
306 device_conditions_(!kPowerRequired, | |
307 kBatteryPercentageHigh, | |
308 net::NetworkChangeNotifier::CONNECTION_3G) {} | |
309 | |
310 RequestCoordinatorTest::~RequestCoordinatorTest() {} | |
311 | |
312 void RequestCoordinatorTest::SetUp() { | |
313 std::unique_ptr<OfflinerPolicy> policy(new OfflinerPolicy()); | |
314 std::unique_ptr<OfflinerFactory> offliner_factory(new OfflinerFactoryStub()); | |
315 // Save the offliner for use by the tests. | |
316 offliner_ = reinterpret_cast<OfflinerStub*>( | |
317 offliner_factory->GetOffliner(policy.get())); | |
318 std::unique_ptr<RequestQueueInMemoryStore> | |
319 store(new RequestQueueInMemoryStore()); | |
320 std::unique_ptr<RequestQueue> queue(new RequestQueue(std::move(store))); | |
321 std::unique_ptr<Scheduler> scheduler_stub(new SchedulerStub()); | |
322 network_quality_estimator_.reset(new NetworkQualityProviderStub()); | |
323 coordinator_.reset(new RequestCoordinator( | |
324 std::move(policy), std::move(offliner_factory), std::move(queue), | |
325 std::move(scheduler_stub), network_quality_estimator_.get())); | |
326 coordinator_->AddObserver(&observer_); | |
327 SetNetworkConnected(true); | |
328 immediate_callback_ = | |
329 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction, | |
330 base::Unretained(this)); | |
331 // Override the normal immediate callback with a wait releasing callback. | |
332 waiting_callback_ = base::Bind( | |
333 &RequestCoordinatorTest::WaitingCallbackFunction, base::Unretained(this)); | |
334 SetDeviceConditionsForTest(device_conditions_); | |
335 EnableOfflinerCallback(true); | |
336 } | |
337 | |
338 void RequestCoordinatorTest::PumpLoop() { | |
339 task_runner_->RunUntilIdle(); | |
340 } | |
341 | |
342 void RequestCoordinatorTest::GetRequestsDone( | |
343 GetRequestsResult result, | |
344 std::vector<std::unique_ptr<SavePageRequest>> requests) { | |
345 last_get_requests_result_ = result; | |
346 last_requests_ = std::move(requests); | |
347 } | |
348 | |
349 void RequestCoordinatorTest::RemoveRequestsDone( | |
350 const MultipleItemStatuses& results) { | |
351 last_remove_results_ = results; | |
352 waiter_.Signal(); | |
353 } | |
354 | |
355 void RequestCoordinatorTest::GetQueuedRequestsDone( | |
356 std::vector<std::unique_ptr<SavePageRequest>> requests) { | |
357 last_requests_ = std::move(requests); | |
358 waiter_.Signal(); | |
359 } | |
360 | |
361 void RequestCoordinatorTest::AddRequestDone(AddRequestResult result, | |
362 const SavePageRequest& request) {} | |
363 | |
364 void RequestCoordinatorTest::SetupForOfflinerDoneCallbackTest( | |
365 offline_pages::SavePageRequest* request) { | |
366 // Mark request as started and add it to the queue, | |
367 // then wait for callback to finish. | |
368 request->MarkAttemptStarted(base::Time::Now()); | |
369 coordinator()->queue()->AddRequest( | |
370 *request, base::Bind(&RequestCoordinatorTest::AddRequestDone, | |
371 base::Unretained(this))); | |
372 PumpLoop(); | |
373 | |
374 // Override the processing callback for test visiblity. | |
375 base::Callback<void(bool)> callback = | |
376 base::Bind(&RequestCoordinatorTest::ImmediateScheduleCallbackFunction, | |
377 base::Unretained(this)); | |
378 coordinator()->SetProcessingCallbackForTest(callback); | |
379 | |
380 // Mock that coordinator is in actively processing state starting now. | |
381 SetProcessingStateForTest( | |
382 RequestCoordinator::ProcessingWindowState::IMMEDIATE_WINDOW); | |
383 SetOperationStartTimeForTest(base::Time::Now()); | |
384 } | |
385 | |
386 void RequestCoordinatorTest::SendOfflinerDoneCallback( | |
387 const SavePageRequest& request, Offliner::RequestStatus status) { | |
388 // Using the fact that the test class is a friend, call to the callback | |
389 coordinator_->OfflinerDoneCallback(request, status); | |
390 } | |
391 | |
392 SavePageRequest RequestCoordinatorTest::AddRequest1() { | |
393 offline_pages::SavePageRequest request1(kRequestId1, kUrl1, kClientId1, | |
394 base::Time::Now(), kUserRequested); | |
395 coordinator()->queue()->AddRequest( | |
396 request1, base::Bind(&RequestCoordinatorTest::AddRequestDone, | |
397 base::Unretained(this))); | |
398 return request1; | |
399 } | |
400 | |
401 SavePageRequest RequestCoordinatorTest::AddRequest2() { | |
402 offline_pages::SavePageRequest request2(kRequestId2, kUrl2, kClientId2, | |
403 base::Time::Now(), kUserRequested); | |
404 coordinator()->queue()->AddRequest( | |
405 request2, base::Bind(&RequestCoordinatorTest::AddRequestDone, | |
406 base::Unretained(this))); | |
407 return request2; | |
408 } | |
409 | |
410 TEST_F(RequestCoordinatorTest, StartProcessingWithNoRequests) { | |
411 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
412 immediate_callback())); | |
413 PumpLoop(); | |
414 | |
415 EXPECT_TRUE(immediate_schedule_callback_called()); | |
416 | |
417 // Verify queue depth UMA for starting scheduled processing on empty queue. | |
418 if (base::SysInfo::IsLowEndDevice()) { | |
419 histograms().ExpectBucketCount( | |
420 "OfflinePages.Background.ScheduledStart.AvailableRequestCount.Svelte", | |
421 0, 1); | |
422 } else { | |
423 histograms().ExpectBucketCount( | |
424 "OfflinePages.Background.ScheduledStart.AvailableRequestCount", 0, 1); | |
425 } | |
426 } | |
427 | |
428 TEST_F(RequestCoordinatorTest, StartProcessingWithRequestInProgress) { | |
429 // Start processing for this request. | |
430 EXPECT_NE( | |
431 coordinator()->SavePageLater( | |
432 kUrl1, kClientId1, kUserRequested, | |
433 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
434 | |
435 // Ensure that the forthcoming request does not finish - we simulate it being | |
436 // in progress by asking it to skip making the completion callback. | |
437 EnableOfflinerCallback(false); | |
438 | |
439 // Sending the request to the offliner should make it busy. | |
440 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
441 immediate_callback())); | |
442 PumpLoop(); | |
443 | |
444 EXPECT_TRUE(is_busy()); | |
445 // Since the offliner is disabled, this callback should not be called. | |
446 EXPECT_FALSE(immediate_schedule_callback_called()); | |
447 | |
448 // Now trying to start processing on another request should return false. | |
449 EXPECT_FALSE(coordinator()->StartProcessing(device_conditions(), | |
450 immediate_callback())); | |
451 } | |
452 | |
453 TEST_F(RequestCoordinatorTest, SavePageLater) { | |
454 // The user-requested request which gets processed by SavePageLater | |
455 // would invoke user request callback. | |
456 coordinator()->SetImmediateScheduleCallbackForTest(immediate_callback()); | |
457 | |
458 EXPECT_NE( | |
459 coordinator()->SavePageLater( | |
460 kUrl1, kClientId1, kUserRequested, | |
461 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
462 | |
463 // Expect that a request got placed on the queue. | |
464 coordinator()->queue()->GetRequests(base::Bind( | |
465 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
466 | |
467 // Wait for callbacks to finish, both request queue and offliner. | |
468 PumpLoop(); | |
469 EXPECT_TRUE(immediate_schedule_callback_called()); | |
470 | |
471 // Check the request queue is as expected. | |
472 EXPECT_EQ(1UL, last_requests().size()); | |
473 EXPECT_EQ(kUrl1, last_requests().at(0)->url()); | |
474 EXPECT_EQ(kClientId1, last_requests().at(0)->client_id()); | |
475 | |
476 // Expect that the scheduler got notified. | |
477 SchedulerStub* scheduler_stub = | |
478 reinterpret_cast<SchedulerStub*>(coordinator()->scheduler()); | |
479 EXPECT_TRUE(scheduler_stub->schedule_called()); | |
480 EXPECT_EQ(coordinator() | |
481 ->GetTriggerConditions(last_requests()[0]->user_requested()) | |
482 .minimum_battery_percentage, | |
483 scheduler_stub->conditions()->minimum_battery_percentage); | |
484 | |
485 // Check that the observer got the notification that a page is available | |
486 EXPECT_TRUE(observer().added_called()); | |
487 | |
488 // Verify queue depth UMA for starting immediate processing. | |
489 if (base::SysInfo::IsLowEndDevice()) { | |
490 histograms().ExpectBucketCount( | |
491 "OfflinePages.Background.ImmediateStart.AvailableRequestCount.Svelte", | |
492 1, 1); | |
493 } else { | |
494 histograms().ExpectBucketCount( | |
495 "OfflinePages.Background.ImmediateStart.AvailableRequestCount", 1, 1); | |
496 } | |
497 } | |
498 | |
499 TEST_F(RequestCoordinatorTest, SavePageLaterFailed) { | |
500 // The user-requested request which gets processed by SavePageLater | |
501 // would invoke user request callback. | |
502 coordinator()->SetImmediateScheduleCallbackForTest(immediate_callback()); | |
503 | |
504 EXPECT_TRUE( | |
505 coordinator()->SavePageLater( | |
506 kUrl1, kClientId1, kUserRequested, | |
507 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER) != 0); | |
508 | |
509 // Expect that a request got placed on the queue. | |
510 coordinator()->queue()->GetRequests( | |
511 base::Bind(&RequestCoordinatorTest::GetRequestsDone, | |
512 base::Unretained(this))); | |
513 | |
514 // Wait for callbacks to finish, both request queue and offliner. | |
515 PumpLoop(); | |
516 | |
517 // On low-end devices the callback will be called with false since the | |
518 // processing started but failed due to svelte devices. | |
519 EXPECT_TRUE(immediate_schedule_callback_called()); | |
520 if (base::SysInfo::IsLowEndDevice()) { | |
521 EXPECT_FALSE(immediate_schedule_callback_result()); | |
522 } else { | |
523 EXPECT_TRUE(immediate_schedule_callback_result()); | |
524 } | |
525 | |
526 // Check the request queue is as expected. | |
527 EXPECT_EQ(1UL, last_requests().size()); | |
528 EXPECT_EQ(kUrl1, last_requests().at(0)->url()); | |
529 EXPECT_EQ(kClientId1, last_requests().at(0)->client_id()); | |
530 | |
531 // Expect that the scheduler got notified. | |
532 SchedulerStub* scheduler_stub = reinterpret_cast<SchedulerStub*>( | |
533 coordinator()->scheduler()); | |
534 EXPECT_TRUE(scheduler_stub->schedule_called()); | |
535 EXPECT_EQ(coordinator() | |
536 ->GetTriggerConditions(last_requests()[0]->user_requested()) | |
537 .minimum_battery_percentage, | |
538 scheduler_stub->conditions()->minimum_battery_percentage); | |
539 | |
540 // Check that the observer got the notification that a page is available | |
541 EXPECT_TRUE(observer().added_called()); | |
542 } | |
543 | |
544 TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceeded) { | |
545 // Add a request to the queue, wait for callbacks to finish. | |
546 offline_pages::SavePageRequest request( | |
547 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested); | |
548 SetupForOfflinerDoneCallbackTest(&request); | |
549 | |
550 // Call the OfflinerDoneCallback to simulate the page being completed, wait | |
551 // for callbacks. | |
552 SendOfflinerDoneCallback(request, Offliner::RequestStatus::SAVED); | |
553 PumpLoop(); | |
554 EXPECT_TRUE(immediate_schedule_callback_called()); | |
555 | |
556 // Verify the request gets removed from the queue, and wait for callbacks. | |
557 coordinator()->queue()->GetRequests( | |
558 base::Bind(&RequestCoordinatorTest::GetRequestsDone, | |
559 base::Unretained(this))); | |
560 PumpLoop(); | |
561 | |
562 // We should not find any requests in the queue anymore. | |
563 // RequestPicker should *not* have tried to start an additional job, | |
564 // because the request queue is empty now. | |
565 EXPECT_EQ(0UL, last_requests().size()); | |
566 // Check that the observer got the notification that we succeeded, and that | |
567 // the request got removed from the queue. | |
568 EXPECT_TRUE(observer().completed_called()); | |
569 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::SUCCESS, | |
570 observer().last_status()); | |
571 } | |
572 | |
573 TEST_F(RequestCoordinatorTest, OfflinerDoneRequestSucceededButLostNetwork) { | |
574 // Add a request to the queue and set offliner done callback for it. | |
575 offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, | |
576 base::Time::Now(), kUserRequested); | |
577 SetupForOfflinerDoneCallbackTest(&request); | |
578 EnableOfflinerCallback(false); | |
579 | |
580 // Add a 2nd request to the queue. | |
581 AddRequest2(); | |
582 | |
583 // Disconnect network. | |
584 SetNetworkConnected(false); | |
585 | |
586 // Call the OfflinerDoneCallback to simulate the page being completed, wait | |
587 // for callbacks. | |
588 SendOfflinerDoneCallback(request, Offliner::RequestStatus::SAVED); | |
589 PumpLoop(); | |
590 EXPECT_TRUE(immediate_schedule_callback_called()); | |
591 | |
592 // Verify not busy with 2nd request (since no connection). | |
593 EXPECT_FALSE(is_busy()); | |
594 | |
595 // Now connect network and verify processing starts. | |
596 SetNetworkConnected(true); | |
597 CallConnectionTypeObserver(); | |
598 PumpLoop(); | |
599 EXPECT_TRUE(is_busy()); | |
600 } | |
601 | |
602 TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) { | |
603 // Add a request to the queue, wait for callbacks to finish. | |
604 offline_pages::SavePageRequest request( | |
605 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested); | |
606 request.set_completed_attempt_count(kMaxCompletedTries - 1); | |
607 SetupForOfflinerDoneCallbackTest(&request); | |
608 // Stop processing before completing the second request on the queue. | |
609 EnableOfflinerCallback(false); | |
610 | |
611 // Add second request to the queue to check handling when first fails. | |
612 AddRequest2(); | |
613 PumpLoop(); | |
614 | |
615 // Call the OfflinerDoneCallback to simulate the request failed, wait | |
616 // for callbacks. | |
617 SendOfflinerDoneCallback(request, | |
618 Offliner::RequestStatus::PRERENDERING_FAILED); | |
619 PumpLoop(); | |
620 | |
621 // For retriable failure, processing should continue to 2nd request so | |
622 // no scheduler callback yet. | |
623 EXPECT_FALSE(immediate_schedule_callback_called()); | |
624 | |
625 // Busy processing 2nd request. | |
626 EXPECT_TRUE(is_busy()); | |
627 | |
628 coordinator()->queue()->GetRequests( | |
629 base::Bind(&RequestCoordinatorTest::GetRequestsDone, | |
630 base::Unretained(this))); | |
631 PumpLoop(); | |
632 | |
633 // Now just one request in the queue since failed request removed | |
634 // (max number of attempts exceeded). | |
635 EXPECT_EQ(1UL, last_requests().size()); | |
636 // Check that the observer got the notification that we failed (and the | |
637 // subsequent notification that the request was removed) since we exceeded | |
638 // retry count. | |
639 EXPECT_TRUE(observer().completed_called()); | |
640 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::RETRY_COUNT_EXCEEDED, | |
641 observer().last_status()); | |
642 } | |
643 | |
644 TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoRetryFailure) { | |
645 // Add a request to the queue, wait for callbacks to finish. | |
646 offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, | |
647 base::Time::Now(), kUserRequested); | |
648 SetupForOfflinerDoneCallbackTest(&request); | |
649 EnableOfflinerCallback(false); | |
650 | |
651 // Add second request to the queue to check handling when first fails. | |
652 AddRequest2(); | |
653 PumpLoop(); | |
654 | |
655 // Call the OfflinerDoneCallback to simulate the request failed, wait | |
656 // for callbacks. | |
657 SendOfflinerDoneCallback( | |
658 request, Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY); | |
659 PumpLoop(); | |
660 | |
661 // For no retry failure, processing should continue to 2nd request so | |
662 // no scheduler callback yet. | |
663 EXPECT_FALSE(immediate_schedule_callback_called()); | |
664 | |
665 // Busy processing 2nd request. | |
666 EXPECT_TRUE(is_busy()); | |
667 | |
668 coordinator()->queue()->GetRequests(base::Bind( | |
669 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
670 PumpLoop(); | |
671 | |
672 // Now just one request in the queue since non-retryable failure. | |
673 EXPECT_EQ(1UL, last_requests().size()); | |
674 // Check that the observer got the notification that we failed (and the | |
675 // subsequent notification that the request was removed). | |
676 EXPECT_TRUE(observer().completed_called()); | |
677 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::PRERENDER_FAILURE, | |
678 observer().last_status()); | |
679 } | |
680 | |
681 TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoNextFailure) { | |
682 // Add a request to the queue, wait for callbacks to finish. | |
683 offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, | |
684 base::Time::Now(), kUserRequested); | |
685 SetupForOfflinerDoneCallbackTest(&request); | |
686 EnableOfflinerCallback(false); | |
687 | |
688 // Add second request to the queue to check handling when first fails. | |
689 AddRequest2(); | |
690 PumpLoop(); | |
691 | |
692 // Call the OfflinerDoneCallback to simulate the request failed, wait | |
693 // for callbacks. | |
694 SendOfflinerDoneCallback( | |
695 request, Offliner::RequestStatus::PRERENDERING_FAILED_NO_NEXT); | |
696 PumpLoop(); | |
697 | |
698 // For no next failure, processing should not continue to 2nd request so | |
699 // expect scheduler callback. | |
700 EXPECT_TRUE(immediate_schedule_callback_called()); | |
701 | |
702 // Not busy for NO_NEXT failure. | |
703 EXPECT_FALSE(is_busy()); | |
704 | |
705 coordinator()->queue()->GetRequests(base::Bind( | |
706 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
707 PumpLoop(); | |
708 | |
709 // Both requests still in queue. | |
710 EXPECT_EQ(2UL, last_requests().size()); | |
711 } | |
712 | |
713 TEST_F(RequestCoordinatorTest, OfflinerDoneForegroundCancel) { | |
714 // Add a request to the queue, wait for callbacks to finish. | |
715 offline_pages::SavePageRequest request( | |
716 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested); | |
717 SetupForOfflinerDoneCallbackTest(&request); | |
718 | |
719 // Call the OfflinerDoneCallback to simulate the request failed, wait | |
720 // for callbacks. | |
721 SendOfflinerDoneCallback(request, | |
722 Offliner::RequestStatus::FOREGROUND_CANCELED); | |
723 PumpLoop(); | |
724 EXPECT_TRUE(immediate_schedule_callback_called()); | |
725 | |
726 // Verify the request is not removed from the queue, and wait for callbacks. | |
727 coordinator()->queue()->GetRequests(base::Bind( | |
728 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
729 PumpLoop(); | |
730 | |
731 // Request no longer in the queue (for single attempt policy). | |
732 EXPECT_EQ(1UL, last_requests().size()); | |
733 // Verify foreground cancel not counted as an attempt after all. | |
734 EXPECT_EQ(0L, last_requests().at(0)->completed_attempt_count()); | |
735 } | |
736 | |
737 TEST_F(RequestCoordinatorTest, OfflinerDonePrerenderingCancel) { | |
738 // Add a request to the queue, wait for callbacks to finish. | |
739 offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, | |
740 base::Time::Now(), kUserRequested); | |
741 SetupForOfflinerDoneCallbackTest(&request); | |
742 | |
743 // Call the OfflinerDoneCallback to simulate the request failed, wait | |
744 // for callbacks. | |
745 SendOfflinerDoneCallback(request, | |
746 Offliner::RequestStatus::PRERENDERING_CANCELED); | |
747 PumpLoop(); | |
748 EXPECT_TRUE(immediate_schedule_callback_called()); | |
749 | |
750 // Verify the request is not removed from the queue, and wait for callbacks. | |
751 coordinator()->queue()->GetRequests(base::Bind( | |
752 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
753 PumpLoop(); | |
754 | |
755 // Request still in the queue. | |
756 EXPECT_EQ(1UL, last_requests().size()); | |
757 // Verify prerendering cancel not counted as an attempt after all. | |
758 const std::unique_ptr<SavePageRequest>& found_request = | |
759 last_requests().front(); | |
760 EXPECT_EQ(0L, found_request->completed_attempt_count()); | |
761 } | |
762 | |
763 // If one item completes, and there are no more user requeted items left, | |
764 // we should make a scheduler entry for a non-user requested item. | |
765 TEST_F(RequestCoordinatorTest, RequestNotPickedDisabledItemsRemain) { | |
766 coordinator()->StartProcessing(device_conditions(), immediate_callback()); | |
767 EXPECT_TRUE(is_starting()); | |
768 | |
769 // Call RequestNotPicked, simulating a request on the disabled list. | |
770 CallRequestNotPicked(false, true); | |
771 PumpLoop(); | |
772 | |
773 EXPECT_FALSE(is_starting()); | |
774 | |
775 // The scheduler should have been called to schedule the disabled task for | |
776 // 5 minutes from now. | |
777 SchedulerStub* scheduler_stub = | |
778 reinterpret_cast<SchedulerStub*>(coordinator()->scheduler()); | |
779 EXPECT_TRUE(scheduler_stub->backup_schedule_called()); | |
780 EXPECT_TRUE(scheduler_stub->unschedule_called()); | |
781 } | |
782 | |
783 // If one item completes, and there are no more user requeted items left, | |
784 // we should make a scheduler entry for a non-user requested item. | |
785 TEST_F(RequestCoordinatorTest, RequestNotPickedNonUserRequestedItemsRemain) { | |
786 coordinator()->StartProcessing(device_conditions(), immediate_callback()); | |
787 EXPECT_TRUE(is_starting()); | |
788 | |
789 // Call RequestNotPicked, and make sure we pick schedule a task for non user | |
790 // requested conditions, with no tasks on the disabled list. | |
791 CallRequestNotPicked(true, false); | |
792 PumpLoop(); | |
793 | |
794 EXPECT_FALSE(is_starting()); | |
795 EXPECT_TRUE(immediate_schedule_callback_called()); | |
796 | |
797 // The scheduler should have been called to schedule the non-user requested | |
798 // task. | |
799 SchedulerStub* scheduler_stub = | |
800 reinterpret_cast<SchedulerStub*>(coordinator()->scheduler()); | |
801 EXPECT_TRUE(scheduler_stub->schedule_called()); | |
802 EXPECT_TRUE(scheduler_stub->unschedule_called()); | |
803 const Scheduler::TriggerConditions* conditions = scheduler_stub->conditions(); | |
804 EXPECT_EQ(conditions->require_power_connected, | |
805 coordinator()->policy()->PowerRequired(!kUserRequested)); | |
806 EXPECT_EQ( | |
807 conditions->minimum_battery_percentage, | |
808 coordinator()->policy()->BatteryPercentageRequired(!kUserRequested)); | |
809 EXPECT_EQ(conditions->require_unmetered_network, | |
810 coordinator()->policy()->UnmeteredNetworkRequired(!kUserRequested)); | |
811 } | |
812 | |
813 TEST_F(RequestCoordinatorTest, SchedulerGetsLeastRestrictiveConditions) { | |
814 // Put two requests on the queue - The first is user requested, and | |
815 // the second is not user requested. | |
816 AddRequest1(); | |
817 offline_pages::SavePageRequest request2(kRequestId2, kUrl2, kClientId2, | |
818 base::Time::Now(), !kUserRequested); | |
819 coordinator()->queue()->AddRequest( | |
820 request2, base::Bind(&RequestCoordinatorTest::AddRequestDone, | |
821 base::Unretained(this))); | |
822 PumpLoop(); | |
823 | |
824 // Trigger the scheduler to schedule for the least restrictive condition. | |
825 ScheduleForTest(); | |
826 PumpLoop(); | |
827 | |
828 // Expect that the scheduler got notified, and it is at user_requested | |
829 // priority. | |
830 SchedulerStub* scheduler_stub = | |
831 reinterpret_cast<SchedulerStub*>(coordinator()->scheduler()); | |
832 const Scheduler::TriggerConditions* conditions = scheduler_stub->conditions(); | |
833 EXPECT_TRUE(scheduler_stub->schedule_called()); | |
834 EXPECT_EQ(conditions->require_power_connected, | |
835 coordinator()->policy()->PowerRequired(kUserRequested)); | |
836 EXPECT_EQ(conditions->minimum_battery_percentage, | |
837 coordinator()->policy()->BatteryPercentageRequired(kUserRequested)); | |
838 EXPECT_EQ(conditions->require_unmetered_network, | |
839 coordinator()->policy()->UnmeteredNetworkRequired(kUserRequested)); | |
840 } | |
841 | |
842 TEST_F(RequestCoordinatorTest, StartProcessingWithLoadingDisabled) { | |
843 // Add a request to the queue, wait for callbacks to finish. | |
844 AddRequest1(); | |
845 PumpLoop(); | |
846 | |
847 DisableLoading(); | |
848 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
849 immediate_callback())); | |
850 | |
851 // Let the async callbacks in the request coordinator run. | |
852 PumpLoop(); | |
853 EXPECT_TRUE(immediate_schedule_callback_called()); | |
854 | |
855 EXPECT_FALSE(is_starting()); | |
856 EXPECT_EQ(Offliner::PRERENDERING_NOT_STARTED, last_offlining_status()); | |
857 } | |
858 | |
859 // This tests a StopProcessing call before we have actually started the | |
860 // prerenderer. | |
861 TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingImmediately) { | |
862 // Add a request to the queue, wait for callbacks to finish. | |
863 AddRequest1(); | |
864 PumpLoop(); | |
865 | |
866 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
867 immediate_callback())); | |
868 EXPECT_TRUE(is_starting()); | |
869 | |
870 // Now, quick, before it can do much (we haven't called PumpLoop), cancel it. | |
871 coordinator()->StopProcessing(Offliner::REQUEST_COORDINATOR_CANCELED); | |
872 | |
873 // Let the async callbacks in the request coordinator run. | |
874 PumpLoop(); | |
875 EXPECT_TRUE(immediate_schedule_callback_called()); | |
876 | |
877 EXPECT_FALSE(is_starting()); | |
878 | |
879 // OfflinerDoneCallback will not end up getting called with status SAVED, | |
880 // since we cancelled the event before it called offliner_->LoadAndSave(). | |
881 EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED, | |
882 last_offlining_status()); | |
883 | |
884 // Since offliner was not started, it will not have seen cancel call. | |
885 EXPECT_FALSE(OfflinerWasCanceled()); | |
886 } | |
887 | |
888 // This tests a StopProcessing call after the prerenderer has been started. | |
889 TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingLater) { | |
890 // Add a request to the queue, wait for callbacks to finish. | |
891 AddRequest1(); | |
892 PumpLoop(); | |
893 | |
894 // Ensure the start processing request stops before the completion callback. | |
895 EnableOfflinerCallback(false); | |
896 | |
897 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
898 immediate_callback())); | |
899 EXPECT_TRUE(is_starting()); | |
900 | |
901 // Let all the async parts of the start processing pipeline run to completion. | |
902 PumpLoop(); | |
903 | |
904 // Observer called for starting processing. | |
905 EXPECT_TRUE(observer().changed_called()); | |
906 EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state()); | |
907 observer().Clear(); | |
908 | |
909 // Since the offliner is disabled, this callback should not be called. | |
910 EXPECT_FALSE(immediate_schedule_callback_called()); | |
911 | |
912 // Coordinator should now be busy. | |
913 EXPECT_TRUE(is_busy()); | |
914 EXPECT_FALSE(is_starting()); | |
915 | |
916 // Now we cancel it while the prerenderer is busy. | |
917 coordinator()->StopProcessing(Offliner::REQUEST_COORDINATOR_CANCELED); | |
918 | |
919 // Let the async callbacks in the cancel run. | |
920 PumpLoop(); | |
921 | |
922 // Observer called for stopped processing. | |
923 EXPECT_TRUE(observer().changed_called()); | |
924 EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state()); | |
925 observer().Clear(); | |
926 | |
927 EXPECT_FALSE(is_busy()); | |
928 | |
929 // OfflinerDoneCallback will not end up getting called with status SAVED, | |
930 // since we cancelled the event before the LoadAndSave completed. | |
931 EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED, | |
932 last_offlining_status()); | |
933 | |
934 // Since offliner was started, it will have seen cancel call. | |
935 EXPECT_TRUE(OfflinerWasCanceled()); | |
936 } | |
937 | |
938 // This tests that canceling a request will result in TryNextRequest() getting | |
939 // called. | |
940 TEST_F(RequestCoordinatorTest, RemoveInflightRequest) { | |
941 // Add a request to the queue, wait for callbacks to finish. | |
942 AddRequest1(); | |
943 PumpLoop(); | |
944 | |
945 // Ensure the start processing request stops before the completion callback. | |
946 EnableOfflinerCallback(false); | |
947 | |
948 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
949 immediate_callback())); | |
950 | |
951 // Let all the async parts of the start processing pipeline run to completion. | |
952 PumpLoop(); | |
953 // Since the offliner is disabled, this callback should not be called. | |
954 EXPECT_FALSE(immediate_schedule_callback_called()); | |
955 | |
956 // Remove the request while it is processing. | |
957 std::vector<int64_t> request_ids{kRequestId1}; | |
958 coordinator()->RemoveRequests( | |
959 request_ids, base::Bind(&RequestCoordinatorTest::RemoveRequestsDone, | |
960 base::Unretained(this))); | |
961 | |
962 // Let the async callbacks in the cancel run. | |
963 PumpLoop(); | |
964 | |
965 // Since offliner was started, it will have seen cancel call. | |
966 EXPECT_TRUE(OfflinerWasCanceled()); | |
967 } | |
968 | |
969 TEST_F(RequestCoordinatorTest, MarkRequestCompleted) { | |
970 int64_t request_id = coordinator()->SavePageLater( | |
971 kUrl1, kClientId1, kUserRequested, | |
972 RequestCoordinator::RequestAvailability::DISABLED_FOR_OFFLINER); | |
973 PumpLoop(); | |
974 EXPECT_NE(request_id, 0l); | |
975 | |
976 // Verify request added in OFFLINING state. | |
977 EXPECT_TRUE(observer().added_called()); | |
978 EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state()); | |
979 | |
980 // Call the method under test, making sure we send SUCCESS to the observer. | |
981 coordinator()->MarkRequestCompleted(request_id); | |
982 PumpLoop(); | |
983 | |
984 // Our observer should have seen SUCCESS instead of REMOVED. | |
985 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::SUCCESS, | |
986 observer().last_status()); | |
987 EXPECT_TRUE(observer().completed_called()); | |
988 } | |
989 | |
990 TEST_F(RequestCoordinatorTest, EnableForOffliner) { | |
991 // Pretend we are on low-end device so immediate start won't happen. | |
992 SetIsLowEndDeviceForTest(true); | |
993 | |
994 int64_t request_id = coordinator()->SavePageLater( | |
995 kUrl1, kClientId1, kUserRequested, | |
996 RequestCoordinator::RequestAvailability::DISABLED_FOR_OFFLINER); | |
997 PumpLoop(); | |
998 EXPECT_NE(request_id, 0l); | |
999 | |
1000 // Verify request added and initial change to OFFLINING (in foreground). | |
1001 EXPECT_TRUE(observer().added_called()); | |
1002 EXPECT_TRUE(observer().changed_called()); | |
1003 EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state()); | |
1004 observer().Clear(); | |
1005 | |
1006 // Ensure that the new request does not finish so we can verify state change. | |
1007 EnableOfflinerCallback(false); | |
1008 | |
1009 coordinator()->EnableForOffliner(request_id, kClientId1); | |
1010 PumpLoop(); | |
1011 | |
1012 // Verify request changed again. | |
1013 EXPECT_TRUE(observer().changed_called()); | |
1014 EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state()); | |
1015 } | |
1016 | |
1017 TEST_F(RequestCoordinatorTest, WatchdogTimeoutForScheduledProcessing) { | |
1018 // Build a request to use with the pre-renderer, and put it on the queue. | |
1019 offline_pages::SavePageRequest request( | |
1020 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested); | |
1021 // Set request to allow one more completed attempt. | |
1022 int max_tries = coordinator()->policy()->GetMaxCompletedTries(); | |
1023 request.set_completed_attempt_count(max_tries - 1); | |
1024 coordinator()->queue()->AddRequest( | |
1025 request, | |
1026 base::Bind(&RequestCoordinatorTest::AddRequestDone, | |
1027 base::Unretained(this))); | |
1028 PumpLoop(); | |
1029 | |
1030 // Ensure that the new request does not finish - we simulate it being | |
1031 // in progress by asking it to skip making the completion callback. | |
1032 EnableOfflinerCallback(false); | |
1033 | |
1034 // Sending the request to the offliner. | |
1035 EXPECT_TRUE( | |
1036 coordinator()->StartProcessing(device_conditions(), waiting_callback())); | |
1037 PumpLoop(); | |
1038 | |
1039 // Advance the mock clock far enough to cause a watchdog timeout | |
1040 AdvanceClockBy(base::TimeDelta::FromSeconds( | |
1041 coordinator() | |
1042 ->policy() | |
1043 ->GetSinglePageTimeLimitWhenBackgroundScheduledInSeconds() + 1)); | |
1044 PumpLoop(); | |
1045 | |
1046 // Wait for timeout to expire. Use a TaskRunner with a DelayedTaskRunner | |
1047 // which won't time out immediately, so the watchdog thread doesn't kill valid | |
1048 // tasks too soon. | |
1049 WaitForCallback(); | |
1050 PumpLoop(); | |
1051 | |
1052 EXPECT_FALSE(is_starting()); | |
1053 EXPECT_FALSE(coordinator()->is_busy()); | |
1054 EXPECT_TRUE(OfflinerWasCanceled()); | |
1055 } | |
1056 | |
1057 TEST_F(RequestCoordinatorTest, WatchdogTimeoutForImmediateProcessing) { | |
1058 // If low end device, pretend it is not so that immediate start happens. | |
1059 SetIsLowEndDeviceForTest(false); | |
1060 | |
1061 // Ensure that the new request does not finish - we simulate it being | |
1062 // in progress by asking it to skip making the completion callback. | |
1063 EnableOfflinerCallback(false); | |
1064 | |
1065 EXPECT_NE( | |
1066 coordinator()->SavePageLater( | |
1067 kUrl1, kClientId1, kUserRequested, | |
1068 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
1069 PumpLoop(); | |
1070 | |
1071 // Verify that immediate start from adding the request did happen. | |
1072 EXPECT_TRUE(coordinator()->is_busy()); | |
1073 | |
1074 // Advance the mock clock 1 second before the watchdog timeout. | |
1075 AdvanceClockBy(base::TimeDelta::FromSeconds( | |
1076 coordinator() | |
1077 ->policy() | |
1078 ->GetSinglePageTimeLimitForImmediateLoadInSeconds() - 1)); | |
1079 PumpLoop(); | |
1080 | |
1081 // Verify still busy. | |
1082 EXPECT_TRUE(coordinator()->is_busy()); | |
1083 EXPECT_FALSE(OfflinerWasCanceled()); | |
1084 | |
1085 // Advance the mock clock past the watchdog timeout now. | |
1086 AdvanceClockBy(base::TimeDelta::FromSeconds(2)); | |
1087 PumpLoop(); | |
1088 | |
1089 // Verify the request timed out. | |
1090 EXPECT_TRUE(OfflinerWasCanceled()); | |
1091 } | |
1092 | |
1093 TEST_F(RequestCoordinatorTest, TimeBudgetExceeded) { | |
1094 EnableOfflinerCallback(false); | |
1095 // Build two requests to use with the pre-renderer, and put it on the queue. | |
1096 AddRequest1(); | |
1097 // The second request will have a larger completed attempt count. | |
1098 offline_pages::SavePageRequest request2(kRequestId1 + 1, kUrl1, kClientId1, | |
1099 base::Time::Now(), kUserRequested); | |
1100 request2.set_completed_attempt_count(kAttemptCount); | |
1101 coordinator()->queue()->AddRequest( | |
1102 request2, base::Bind(&RequestCoordinatorTest::AddRequestDone, | |
1103 base::Unretained(this))); | |
1104 PumpLoop(); | |
1105 | |
1106 // Sending the request to the offliner. | |
1107 EXPECT_TRUE( | |
1108 coordinator()->StartProcessing(device_conditions(), waiting_callback())); | |
1109 PumpLoop(); | |
1110 | |
1111 // Advance the mock clock far enough to exceed our time budget. | |
1112 // The first request will time out, and because we are over time budget, | |
1113 // the second request will not be started. | |
1114 AdvanceClockBy(base::TimeDelta::FromSeconds(kTestTimeBudgetSeconds)); | |
1115 PumpLoop(); | |
1116 | |
1117 // TryNextRequest should decide that there is no more work to be done, | |
1118 // and call back to the scheduler, even though there is another request in the | |
1119 // queue. Both requests should be left in the queue. | |
1120 coordinator()->queue()->GetRequests( | |
1121 base::Bind(&RequestCoordinatorTest::GetRequestsDone, | |
1122 base::Unretained(this))); | |
1123 PumpLoop(); | |
1124 | |
1125 // We should find two requests in the queue. | |
1126 // The first request should now have a completed count of 1. | |
1127 EXPECT_EQ(2UL, last_requests().size()); | |
1128 EXPECT_EQ(1L, last_requests().at(0)->completed_attempt_count()); | |
1129 } | |
1130 | |
1131 TEST_F(RequestCoordinatorTest, TryNextRequestWithNoNetwork) { | |
1132 SavePageRequest request1 = AddRequest1(); | |
1133 AddRequest2(); | |
1134 PumpLoop(); | |
1135 | |
1136 // Set up for the call to StartProcessing. | |
1137 EnableOfflinerCallback(false); | |
1138 | |
1139 // Sending the request to the offliner. | |
1140 EXPECT_TRUE( | |
1141 coordinator()->StartProcessing(device_conditions(), waiting_callback())); | |
1142 PumpLoop(); | |
1143 EXPECT_TRUE(coordinator()->is_busy()); | |
1144 | |
1145 // Now lose the network connection. | |
1146 SetNetworkConnected(false); | |
1147 | |
1148 // Complete first request and then TryNextRequest should decide not | |
1149 // to pick another request (because of no network connection). | |
1150 SendOfflinerDoneCallback(request1, Offliner::RequestStatus::SAVED); | |
1151 PumpLoop(); | |
1152 | |
1153 // Not starting nor busy with next request. | |
1154 EXPECT_FALSE(coordinator()->is_starting()); | |
1155 EXPECT_FALSE(coordinator()->is_busy()); | |
1156 | |
1157 // Get queued requests. | |
1158 coordinator()->queue()->GetRequests(base::Bind( | |
1159 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
1160 PumpLoop(); | |
1161 | |
1162 // We should find one request in the queue. | |
1163 EXPECT_EQ(1UL, last_requests().size()); | |
1164 } | |
1165 | |
1166 TEST_F(RequestCoordinatorTest, GetAllRequests) { | |
1167 // Add two requests to the queue. | |
1168 AddRequest1(); | |
1169 AddRequest2(); | |
1170 PumpLoop(); | |
1171 | |
1172 // Start the async status fetching. | |
1173 coordinator()->GetAllRequests(base::Bind( | |
1174 &RequestCoordinatorTest::GetQueuedRequestsDone, base::Unretained(this))); | |
1175 PumpLoop(); | |
1176 | |
1177 // Wait for async get to finish. | |
1178 WaitForCallback(); | |
1179 PumpLoop(); | |
1180 | |
1181 // Check that the statuses found in the callback match what we expect. | |
1182 EXPECT_EQ(2UL, last_requests().size()); | |
1183 EXPECT_EQ(kRequestId1, last_requests().at(0)->request_id()); | |
1184 EXPECT_EQ(kRequestId2, last_requests().at(1)->request_id()); | |
1185 } | |
1186 | |
1187 #if defined(OS_IOS) | |
1188 // Flaky on IOS. http://crbug/663311 | |
1189 #define MAYBE_PauseAndResumeObserver DISABLED_PauseAndResumeObserver | |
1190 #else | |
1191 #define MAYBE_PauseAndResumeObserver PauseAndResumeObserver | |
1192 #endif | |
1193 TEST_F(RequestCoordinatorTest, MAYBE_PauseAndResumeObserver) { | |
1194 // Add a request to the queue. | |
1195 AddRequest1(); | |
1196 PumpLoop(); | |
1197 | |
1198 // Pause the request. | |
1199 std::vector<int64_t> request_ids; | |
1200 request_ids.push_back(kRequestId1); | |
1201 coordinator()->PauseRequests(request_ids); | |
1202 PumpLoop(); | |
1203 | |
1204 EXPECT_TRUE(observer().changed_called()); | |
1205 EXPECT_EQ(SavePageRequest::RequestState::PAUSED, observer().state()); | |
1206 | |
1207 // Clear out the observer before the next call. | |
1208 observer().Clear(); | |
1209 | |
1210 // Resume the request. | |
1211 coordinator()->ResumeRequests(request_ids); | |
1212 PumpLoop(); | |
1213 | |
1214 EXPECT_TRUE(observer().changed_called()); | |
1215 | |
1216 // Now whether request is offlining or just available depends on whether test | |
1217 // is run on svelte device or not. | |
1218 if (base::SysInfo::IsLowEndDevice()) { | |
1219 EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state()); | |
1220 } else { | |
1221 EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state()); | |
1222 } | |
1223 } | |
1224 | |
1225 TEST_F(RequestCoordinatorTest, RemoveRequest) { | |
1226 // Add a request to the queue. | |
1227 AddRequest1(); | |
1228 PumpLoop(); | |
1229 | |
1230 // Remove the request. | |
1231 std::vector<int64_t> request_ids; | |
1232 request_ids.push_back(kRequestId1); | |
1233 coordinator()->RemoveRequests( | |
1234 request_ids, base::Bind(&RequestCoordinatorTest::RemoveRequestsDone, | |
1235 base::Unretained(this))); | |
1236 | |
1237 PumpLoop(); | |
1238 WaitForCallback(); | |
1239 PumpLoop(); | |
1240 | |
1241 EXPECT_TRUE(observer().completed_called()); | |
1242 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::REMOVED, | |
1243 observer().last_status()); | |
1244 EXPECT_EQ(1UL, last_remove_results().size()); | |
1245 EXPECT_EQ(kRequestId1, std::get<0>(last_remove_results().at(0))); | |
1246 } | |
1247 | |
1248 TEST_F(RequestCoordinatorTest, | |
1249 SavePageStartsProcessingWhenConnectedAndNotLowEndDevice) { | |
1250 // Turn off the callback so that the request stops before processing in | |
1251 // PumpLoop. | |
1252 EnableOfflinerCallback(false); | |
1253 EXPECT_NE( | |
1254 coordinator()->SavePageLater( | |
1255 kUrl1, kClientId1, kUserRequested, | |
1256 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
1257 PumpLoop(); | |
1258 | |
1259 // Now whether processing triggered immediately depends on whether test | |
1260 // is run on svelte device or not. | |
1261 if (base::SysInfo::IsLowEndDevice()) { | |
1262 EXPECT_FALSE(is_busy()); | |
1263 } else { | |
1264 EXPECT_TRUE(is_busy()); | |
1265 } | |
1266 } | |
1267 | |
1268 TEST_F(RequestCoordinatorTest, | |
1269 SavePageStartsProcessingWhenConnectedOnLowEndDeviceIfFlagEnabled) { | |
1270 // Mark device as low-end device. | |
1271 SetIsLowEndDeviceForTest(true); | |
1272 EXPECT_FALSE(offline_pages::IsOfflinePagesSvelteConcurrentLoadingEnabled()); | |
1273 | |
1274 // Make a request. | |
1275 EXPECT_NE(coordinator()->SavePageLater( | |
1276 kUrl1, kClientId1, kUserRequested, | |
1277 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), | |
1278 0); | |
1279 PumpLoop(); | |
1280 | |
1281 // Verify not immediately busy (since low-end device). | |
1282 EXPECT_FALSE(is_busy()); | |
1283 | |
1284 // Set feature flag to allow concurrent loads. | |
1285 base::test::ScopedFeatureList scoped_feature_list; | |
1286 scoped_feature_list.InitAndEnableFeature( | |
1287 kOfflinePagesSvelteConcurrentLoadingFeature); | |
1288 EXPECT_TRUE(offline_pages::IsOfflinePagesSvelteConcurrentLoadingEnabled()); | |
1289 | |
1290 // Turn off the callback so that the request stops before processing in | |
1291 // PumpLoop. | |
1292 EnableOfflinerCallback(false); | |
1293 | |
1294 // Make another request. | |
1295 EXPECT_NE(coordinator()->SavePageLater( | |
1296 kUrl2, kClientId2, kUserRequested, | |
1297 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), | |
1298 0); | |
1299 PumpLoop(); | |
1300 | |
1301 // Verify immediate processing did start this time. | |
1302 EXPECT_TRUE(is_busy()); | |
1303 } | |
1304 | |
1305 TEST_F(RequestCoordinatorTest, SavePageDoesntStartProcessingWhenDisconnected) { | |
1306 // If low end device, pretend it is not so that immediate start allowed. | |
1307 SetIsLowEndDeviceForTest(false); | |
1308 | |
1309 SetNetworkConnected(false); | |
1310 EnableOfflinerCallback(false); | |
1311 EXPECT_NE( | |
1312 coordinator()->SavePageLater( | |
1313 kUrl1, kClientId1, kUserRequested, | |
1314 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
1315 PumpLoop(); | |
1316 EXPECT_FALSE(is_busy()); | |
1317 | |
1318 // Now connect network and verify processing starts. | |
1319 SetNetworkConnected(true); | |
1320 CallConnectionTypeObserver(); | |
1321 PumpLoop(); | |
1322 EXPECT_TRUE(is_busy()); | |
1323 } | |
1324 | |
1325 TEST_F(RequestCoordinatorTest, | |
1326 SavePageDoesStartProcessingWhenPoorlyConnected) { | |
1327 // Set specific network type for 2G with poor effective connection. | |
1328 SetNetworkConditionsForTest( | |
1329 net::NetworkChangeNotifier::ConnectionType::CONNECTION_2G); | |
1330 SetEffectiveConnectionTypeForTest( | |
1331 net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_SLOW_2G); | |
1332 | |
1333 // Turn off the callback so that the request stops before processing in | |
1334 // PumpLoop. | |
1335 EnableOfflinerCallback(false); | |
1336 | |
1337 EXPECT_NE( | |
1338 coordinator()->SavePageLater( | |
1339 kUrl1, kClientId1, kUserRequested, | |
1340 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
1341 PumpLoop(); | |
1342 EXPECT_TRUE(is_busy()); | |
1343 } | |
1344 | |
1345 TEST_F(RequestCoordinatorTest, | |
1346 ResumeStartsProcessingWhenConnectedAndNotLowEndDevice) { | |
1347 // Start unconnected. | |
1348 SetNetworkConnected(false); | |
1349 | |
1350 // Turn off the callback so that the request stops before processing in | |
1351 // PumpLoop. | |
1352 EnableOfflinerCallback(false); | |
1353 | |
1354 // Add a request to the queue. | |
1355 AddRequest1(); | |
1356 PumpLoop(); | |
1357 EXPECT_FALSE(is_busy()); | |
1358 | |
1359 // Pause the request. | |
1360 std::vector<int64_t> request_ids; | |
1361 request_ids.push_back(kRequestId1); | |
1362 coordinator()->PauseRequests(request_ids); | |
1363 PumpLoop(); | |
1364 | |
1365 // Resume the request while disconnected. | |
1366 coordinator()->ResumeRequests(request_ids); | |
1367 PumpLoop(); | |
1368 EXPECT_FALSE(is_busy()); | |
1369 | |
1370 // Pause the request again. | |
1371 coordinator()->PauseRequests(request_ids); | |
1372 PumpLoop(); | |
1373 | |
1374 // Now simulate reasonable connection. | |
1375 SetNetworkConnected(true); | |
1376 | |
1377 // Resume the request while connected. | |
1378 coordinator()->ResumeRequests(request_ids); | |
1379 EXPECT_FALSE(is_busy()); | |
1380 PumpLoop(); | |
1381 | |
1382 // Now whether processing triggered immediately depends on whether test | |
1383 // is run on svelte device or not. | |
1384 if (base::SysInfo::IsLowEndDevice()) { | |
1385 EXPECT_FALSE(is_busy()); | |
1386 } else { | |
1387 EXPECT_TRUE(is_busy()); | |
1388 } | |
1389 } | |
1390 | |
1391 } // namespace offline_pages | |
OLD | NEW |