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/pick_request_task_factory.h" | |
30 #include "components/offline_pages/background/request_queue.h" | |
31 #include "components/offline_pages/background/request_queue_in_memory_store.h" | |
32 #include "components/offline_pages/background/save_page_request.h" | |
33 #include "components/offline_pages/background/scheduler.h" | |
34 #include "components/offline_pages/background/scheduler_stub.h" | |
35 #include "components/offline_pages/offline_page_feature.h" | |
36 #include "testing/gtest/include/gtest/gtest.h" | |
37 | |
38 namespace offline_pages { | |
39 | |
40 namespace { | |
41 // put test constants here | |
42 const GURL kUrl1("http://universe.com/everything"); | |
43 const GURL kUrl2("http://universe.com/toinfinityandbeyond"); | |
44 const std::string kClientNamespace("bookmark"); | |
45 const std::string kId1("42"); | |
46 const std::string kId2("life*universe+everything"); | |
47 const ClientId kClientId1(kClientNamespace, kId1); | |
48 const ClientId kClientId2(kClientNamespace, kId2); | |
49 const int kRequestId1(1); | |
50 const int kRequestId2(2); | |
51 const long kTestTimeBudgetSeconds = 200; | |
52 const int kBatteryPercentageHigh = 75; | |
53 const int kMaxCompletedTries = 3; | |
54 const bool kPowerRequired = true; | |
55 const bool kUserRequested = true; | |
56 const int kAttemptCount = 1; | |
57 } // namespace | |
58 | |
59 class ObserverStub : public RequestCoordinator::Observer { | |
60 public: | |
61 ObserverStub() | |
62 : added_called_(false), | |
63 completed_called_(false), | |
64 changed_called_(false), | |
65 last_status_(RequestCoordinator::BackgroundSavePageResult::SUCCESS), | |
66 state_(SavePageRequest::RequestState::OFFLINING) {} | |
67 | |
68 void Clear() { | |
69 added_called_ = false; | |
70 completed_called_ = false; | |
71 changed_called_ = false; | |
72 state_ = SavePageRequest::RequestState::OFFLINING; | |
73 last_status_ = RequestCoordinator::BackgroundSavePageResult::SUCCESS; | |
74 } | |
75 | |
76 void OnAdded(const SavePageRequest& request) override { | |
77 added_called_ = true; | |
78 } | |
79 | |
80 void OnCompleted( | |
81 const SavePageRequest& request, | |
82 RequestCoordinator::BackgroundSavePageResult status) override { | |
83 completed_called_ = true; | |
84 last_status_ = status; | |
85 } | |
86 | |
87 void OnChanged(const SavePageRequest& request) override { | |
88 changed_called_ = true; | |
89 state_ = request.request_state(); | |
90 } | |
91 | |
92 bool added_called() { return added_called_; } | |
93 bool completed_called() { return completed_called_; } | |
94 bool changed_called() { return changed_called_; } | |
95 RequestCoordinator::BackgroundSavePageResult last_status() { | |
96 return last_status_; | |
97 } | |
98 SavePageRequest::RequestState state() { return state_; } | |
99 | |
100 private: | |
101 bool added_called_; | |
102 bool completed_called_; | |
103 bool changed_called_; | |
104 RequestCoordinator::BackgroundSavePageResult last_status_; | |
105 SavePageRequest::RequestState state_; | |
106 }; | |
107 | |
108 class RequestCoordinatorTest | |
109 : public testing::Test { | |
110 public: | |
111 RequestCoordinatorTest(); | |
112 ~RequestCoordinatorTest() override; | |
113 | |
114 void SetUp() override; | |
115 | |
116 void PumpLoop(); | |
117 | |
118 RequestCoordinator* coordinator() { | |
119 return coordinator_.get(); | |
120 } | |
121 | |
122 bool is_busy() { | |
123 return coordinator_->is_busy(); | |
124 } | |
125 | |
126 bool is_starting() { return coordinator_->is_starting(); } | |
127 | |
128 // Empty callback function. | |
129 void ImmediateScheduleCallbackFunction(bool result) { | |
130 immediate_schedule_callback_called_ = true; | |
131 immediate_schedule_callback_result_ = result; | |
132 } | |
133 | |
134 // Callback function which releases a wait for it. | |
135 void WaitingCallbackFunction(bool result) { | |
136 waiter_.Signal(); | |
137 } | |
138 | |
139 net::NetworkChangeNotifier::ConnectionType GetConnectionType() { | |
140 return coordinator()->GetConnectionType(); | |
141 } | |
142 | |
143 // Callback for Add requests. | |
144 void AddRequestDone(AddRequestResult result, const SavePageRequest& request); | |
145 | |
146 // Callback for getting requests. | |
147 void GetRequestsDone(GetRequestsResult result, | |
148 std::vector<std::unique_ptr<SavePageRequest>> requests); | |
149 | |
150 // Callback for removing requests. | |
151 void RemoveRequestsDone(const MultipleItemStatuses& results); | |
152 | |
153 // Callback for getting request statuses. | |
154 void GetQueuedRequestsDone( | |
155 std::vector<std::unique_ptr<SavePageRequest>> requests); | |
156 | |
157 void SetupForOfflinerDoneCallbackTest( | |
158 offline_pages::SavePageRequest* request); | |
159 | |
160 void SendOfflinerDoneCallback(const SavePageRequest& request, | |
161 Offliner::RequestStatus status); | |
162 | |
163 GetRequestsResult last_get_requests_result() const { | |
164 return last_get_requests_result_; | |
165 } | |
166 | |
167 const std::vector<std::unique_ptr<SavePageRequest>>& last_requests() const { | |
168 return last_requests_; | |
169 } | |
170 | |
171 const MultipleItemStatuses& last_remove_results() const { | |
172 return last_remove_results_; | |
173 } | |
174 | |
175 void DisableLoading() { | |
176 offliner_->disable_loading(); | |
177 } | |
178 | |
179 void EnableOfflinerCallback(bool enable) { | |
180 offliner_->enable_callback(enable); | |
181 } | |
182 | |
183 void SetNetworkConditionsForTest( | |
184 net::NetworkChangeNotifier::ConnectionType connection) { | |
185 coordinator()->SetNetworkConditionsForTest(connection); | |
186 } | |
187 | |
188 void SetEffectiveConnectionTypeForTest(net::EffectiveConnectionType type) { | |
189 network_quality_estimator_->SetEffectiveConnectionTypeForTest(type); | |
190 } | |
191 | |
192 void SetNetworkConnected(bool connected) { | |
193 if (connected) { | |
194 SetNetworkConditionsForTest( | |
195 net::NetworkChangeNotifier::ConnectionType::CONNECTION_3G); | |
196 SetEffectiveConnectionTypeForTest( | |
197 net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_3G); | |
198 } else { | |
199 SetNetworkConditionsForTest( | |
200 net::NetworkChangeNotifier::ConnectionType::CONNECTION_NONE); | |
201 SetEffectiveConnectionTypeForTest( | |
202 net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_OFFLINE); | |
203 } | |
204 } | |
205 | |
206 void SetIsLowEndDeviceForTest(bool is_low_end_device) { | |
207 coordinator()->is_low_end_device_ = is_low_end_device; | |
208 } | |
209 | |
210 void SetProcessingStateForTest( | |
211 RequestCoordinator::ProcessingWindowState processing_state) { | |
212 coordinator()->processing_state_ = processing_state; | |
213 } | |
214 | |
215 void SetOperationStartTimeForTest(base::Time start_time) { | |
216 coordinator()->operation_start_time_ = start_time; | |
217 } | |
218 | |
219 void ScheduleForTest() { coordinator_->ScheduleAsNeeded(); } | |
220 | |
221 void CallRequestNotPicked(bool non_user_requested_tasks_remaining, | |
222 bool disabled_tasks_remaining) { | |
223 if (disabled_tasks_remaining) | |
224 coordinator_->disabled_requests_.insert(kRequestId1); | |
225 else | |
226 coordinator_->disabled_requests_.clear(); | |
227 | |
228 coordinator_->RequestNotPicked(non_user_requested_tasks_remaining); | |
229 } | |
230 | |
231 void SetDeviceConditionsForTest(DeviceConditions device_conditions) { | |
232 coordinator_->SetDeviceConditionsForTest(device_conditions); | |
233 } | |
234 | |
235 void WaitForCallback() { | |
236 waiter_.Wait(); | |
237 } | |
238 | |
239 void AdvanceClockBy(base::TimeDelta delta) { | |
240 task_runner_->FastForwardBy(delta); | |
241 } | |
242 | |
243 SavePageRequest AddRequest1(); | |
244 | |
245 SavePageRequest AddRequest2(); | |
246 | |
247 Offliner::RequestStatus last_offlining_status() const { | |
248 return coordinator_->last_offlining_status_; | |
249 } | |
250 | |
251 bool OfflinerWasCanceled() const { return offliner_->cancel_called(); } | |
252 | |
253 ObserverStub observer() { return observer_; } | |
254 | |
255 DeviceConditions device_conditions() { return device_conditions_; } | |
256 | |
257 base::Callback<void(bool)> immediate_callback() { | |
258 return immediate_callback_; | |
259 } | |
260 | |
261 base::Callback<void(bool)> waiting_callback() { return waiting_callback_; } | |
262 bool immediate_schedule_callback_called() const { | |
263 return immediate_schedule_callback_called_; | |
264 } | |
265 | |
266 bool immediate_schedule_callback_result() const { | |
267 return immediate_schedule_callback_result_; | |
268 } | |
269 | |
270 const base::HistogramTester& histograms() const { return histogram_tester_; } | |
271 | |
272 private: | |
273 GetRequestsResult last_get_requests_result_; | |
274 MultipleItemStatuses last_remove_results_; | |
275 std::vector<std::unique_ptr<SavePageRequest>> last_requests_; | |
276 scoped_refptr<base::TestMockTimeTaskRunner> task_runner_; | |
277 base::ThreadTaskRunnerHandle task_runner_handle_; | |
278 std::unique_ptr<NetworkQualityProviderStub> network_quality_estimator_; | |
279 std::unique_ptr<RequestCoordinator> coordinator_; | |
280 OfflinerStub* offliner_; | |
281 base::WaitableEvent waiter_; | |
282 ObserverStub observer_; | |
283 bool immediate_schedule_callback_called_; | |
284 bool immediate_schedule_callback_result_; | |
285 DeviceConditions device_conditions_; | |
286 base::Callback<void(bool)> immediate_callback_; | |
287 base::Callback<void(bool)> waiting_callback_; | |
288 base::HistogramTester histogram_tester_; | |
289 }; | |
290 | |
291 RequestCoordinatorTest::RequestCoordinatorTest() | |
292 : last_get_requests_result_(GetRequestsResult::STORE_FAILURE), | |
293 task_runner_(new base::TestMockTimeTaskRunner), | |
294 task_runner_handle_(task_runner_), | |
295 offliner_(nullptr), | |
296 waiter_(base::WaitableEvent::ResetPolicy::MANUAL, | |
297 base::WaitableEvent::InitialState::NOT_SIGNALED), | |
298 immediate_schedule_callback_called_(false), | |
299 immediate_schedule_callback_result_(false), | |
300 device_conditions_(!kPowerRequired, | |
301 kBatteryPercentageHigh, | |
302 net::NetworkChangeNotifier::CONNECTION_3G) {} | |
303 | |
304 RequestCoordinatorTest::~RequestCoordinatorTest() {} | |
305 | |
306 void RequestCoordinatorTest::SetUp() { | |
307 std::unique_ptr<OfflinerPolicy> policy(new OfflinerPolicy()); | |
308 std::unique_ptr<OfflinerFactory> offliner_factory(new OfflinerFactoryStub()); | |
309 // Save the offliner for use by the tests. | |
310 offliner_ = reinterpret_cast<OfflinerStub*>( | |
311 offliner_factory->GetOffliner(policy.get())); | |
312 std::unique_ptr<RequestQueueInMemoryStore> | |
313 store(new RequestQueueInMemoryStore()); | |
314 std::unique_ptr<RequestQueue> queue(new RequestQueue(std::move(store))); | |
315 std::unique_ptr<Scheduler> scheduler_stub(new SchedulerStub()); | |
316 network_quality_estimator_.reset(new NetworkQualityProviderStub()); | |
317 coordinator_.reset(new RequestCoordinator( | |
318 std::move(policy), std::move(offliner_factory), std::move(queue), | |
319 std::move(scheduler_stub), network_quality_estimator_.get())); | |
320 coordinator_->AddObserver(&observer_); | |
321 SetNetworkConnected(true); | |
322 std::unique_ptr<PickRequestTaskFactory> picker_factory( | |
323 new PickRequestTaskFactory( | |
324 coordinator_->policy(), | |
325 static_cast<RequestNotifier*>(coordinator_.get()), | |
326 coordinator_->GetLogger())); | |
327 coordinator_->queue()->SetPickerFactory(std::move(picker_factory)); | |
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, OfflinerDoneRequestFailed) { | |
574 // Add a request to the queue, wait for callbacks to finish. | |
575 offline_pages::SavePageRequest request( | |
576 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested); | |
577 request.set_completed_attempt_count(kMaxCompletedTries - 1); | |
578 SetupForOfflinerDoneCallbackTest(&request); | |
579 // Stop processing before completing the second request on the queue. | |
580 EnableOfflinerCallback(false); | |
581 | |
582 // Add second request to the queue to check handling when first fails. | |
583 AddRequest2(); | |
584 PumpLoop(); | |
585 | |
586 // Call the OfflinerDoneCallback to simulate the request failed, wait | |
587 // for callbacks. | |
588 SendOfflinerDoneCallback(request, | |
589 Offliner::RequestStatus::PRERENDERING_FAILED); | |
590 PumpLoop(); | |
591 | |
592 // For retriable failure, processing should stop and scheduler callback | |
593 // called (so that request can be retried first next processing window). | |
594 EXPECT_TRUE(immediate_schedule_callback_called()); | |
595 | |
596 // TODO(dougarnett): Consider injecting mock RequestPicker for this test | |
597 // and verifying that there is no attempt to pick another request following | |
598 // this failure code. | |
599 | |
600 coordinator()->queue()->GetRequests( | |
601 base::Bind(&RequestCoordinatorTest::GetRequestsDone, | |
602 base::Unretained(this))); | |
603 PumpLoop(); | |
604 | |
605 // Now just one request in the queue since failed request removed | |
606 // (max number of attempts exceeded). | |
607 EXPECT_EQ(1UL, last_requests().size()); | |
608 // Check that the observer got the notification that we failed (and the | |
609 // subsequent notification that the request was removed). | |
610 EXPECT_TRUE(observer().completed_called()); | |
611 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::RETRY_COUNT_EXCEEDED, | |
612 observer().last_status()); | |
613 } | |
614 | |
615 TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailedNoRetryFailure) { | |
616 // Add a request to the queue, wait for callbacks to finish. | |
617 offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, | |
618 base::Time::Now(), kUserRequested); | |
619 SetupForOfflinerDoneCallbackTest(&request); | |
620 EnableOfflinerCallback(false); | |
621 | |
622 // Add second request to the queue to check handling when first fails. | |
623 AddRequest2(); | |
624 PumpLoop(); | |
625 | |
626 // Call the OfflinerDoneCallback to simulate the request failed, wait | |
627 // for callbacks. | |
628 SendOfflinerDoneCallback( | |
629 request, Offliner::RequestStatus::PRERENDERING_FAILED_NO_RETRY); | |
630 PumpLoop(); | |
631 | |
632 // For no retry failure, processing should continue to 2nd request so | |
633 // no scheduler callback yet. | |
634 EXPECT_FALSE(immediate_schedule_callback_called()); | |
635 | |
636 // TODO(dougarnett): Consider injecting mock RequestPicker for this test | |
637 // and verifying that there is as attempt to pick another request following | |
638 // this non-retryable failure code. | |
639 | |
640 coordinator()->queue()->GetRequests(base::Bind( | |
641 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
642 PumpLoop(); | |
643 | |
644 // Now just one request in the queue since non-retryable failure. | |
645 EXPECT_EQ(1UL, last_requests().size()); | |
646 // Check that the observer got the notification that we failed (and the | |
647 // subsequent notification that the request was removed). | |
648 EXPECT_TRUE(observer().completed_called()); | |
649 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::PRERENDER_FAILURE, | |
650 observer().last_status()); | |
651 } | |
652 | |
653 TEST_F(RequestCoordinatorTest, OfflinerDoneForegroundCancel) { | |
654 // Add a request to the queue, wait for callbacks to finish. | |
655 offline_pages::SavePageRequest request( | |
656 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested); | |
657 SetupForOfflinerDoneCallbackTest(&request); | |
658 | |
659 // Call the OfflinerDoneCallback to simulate the request failed, wait | |
660 // for callbacks. | |
661 SendOfflinerDoneCallback(request, | |
662 Offliner::RequestStatus::FOREGROUND_CANCELED); | |
663 PumpLoop(); | |
664 EXPECT_TRUE(immediate_schedule_callback_called()); | |
665 | |
666 // Verify the request is not removed from the queue, and wait for callbacks. | |
667 coordinator()->queue()->GetRequests(base::Bind( | |
668 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
669 PumpLoop(); | |
670 | |
671 // Request no longer in the queue (for single attempt policy). | |
672 EXPECT_EQ(1UL, last_requests().size()); | |
673 // Verify foreground cancel not counted as an attempt after all. | |
674 EXPECT_EQ(0L, last_requests().at(0)->completed_attempt_count()); | |
675 } | |
676 | |
677 TEST_F(RequestCoordinatorTest, OfflinerDonePrerenderingCancel) { | |
678 // Add a request to the queue, wait for callbacks to finish. | |
679 offline_pages::SavePageRequest request(kRequestId1, kUrl1, kClientId1, | |
680 base::Time::Now(), kUserRequested); | |
681 SetupForOfflinerDoneCallbackTest(&request); | |
682 | |
683 // Call the OfflinerDoneCallback to simulate the request failed, wait | |
684 // for callbacks. | |
685 SendOfflinerDoneCallback(request, | |
686 Offliner::RequestStatus::PRERENDERING_CANCELED); | |
687 PumpLoop(); | |
688 EXPECT_TRUE(immediate_schedule_callback_called()); | |
689 | |
690 // Verify the request is not removed from the queue, and wait for callbacks. | |
691 coordinator()->queue()->GetRequests(base::Bind( | |
692 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
693 PumpLoop(); | |
694 | |
695 // Request still in the queue. | |
696 EXPECT_EQ(1UL, last_requests().size()); | |
697 // Verify prerendering cancel not counted as an attempt after all. | |
698 const std::unique_ptr<SavePageRequest>& found_request = | |
699 last_requests().front(); | |
700 EXPECT_EQ(0L, found_request->completed_attempt_count()); | |
701 } | |
702 | |
703 // If one item completes, and there are no more user requeted items left, | |
704 // we should make a scheduler entry for a non-user requested item. | |
705 TEST_F(RequestCoordinatorTest, RequestNotPickedDisabledItemsRemain) { | |
706 coordinator()->StartProcessing(device_conditions(), immediate_callback()); | |
707 EXPECT_TRUE(is_starting()); | |
708 | |
709 // Call RequestNotPicked, simulating a request on the disabled list. | |
710 CallRequestNotPicked(false, true); | |
711 PumpLoop(); | |
712 | |
713 EXPECT_FALSE(is_starting()); | |
714 | |
715 // The scheduler should have been called to schedule the disabled task for | |
716 // 5 minutes from now. | |
717 SchedulerStub* scheduler_stub = | |
718 reinterpret_cast<SchedulerStub*>(coordinator()->scheduler()); | |
719 EXPECT_TRUE(scheduler_stub->backup_schedule_called()); | |
720 EXPECT_TRUE(scheduler_stub->unschedule_called()); | |
721 } | |
722 | |
723 // If one item completes, and there are no more user requeted items left, | |
724 // we should make a scheduler entry for a non-user requested item. | |
725 TEST_F(RequestCoordinatorTest, RequestNotPickedNonUserRequestedItemsRemain) { | |
726 coordinator()->StartProcessing(device_conditions(), immediate_callback()); | |
727 EXPECT_TRUE(is_starting()); | |
728 | |
729 // Call RequestNotPicked, and make sure we pick schedule a task for non user | |
730 // requested conditions, with no tasks on the disabled list. | |
731 CallRequestNotPicked(true, false); | |
732 PumpLoop(); | |
733 | |
734 EXPECT_FALSE(is_starting()); | |
735 EXPECT_TRUE(immediate_schedule_callback_called()); | |
736 | |
737 // The scheduler should have been called to schedule the non-user requested | |
738 // task. | |
739 SchedulerStub* scheduler_stub = | |
740 reinterpret_cast<SchedulerStub*>(coordinator()->scheduler()); | |
741 EXPECT_TRUE(scheduler_stub->schedule_called()); | |
742 EXPECT_TRUE(scheduler_stub->unschedule_called()); | |
743 const Scheduler::TriggerConditions* conditions = scheduler_stub->conditions(); | |
744 EXPECT_EQ(conditions->require_power_connected, | |
745 coordinator()->policy()->PowerRequired(!kUserRequested)); | |
746 EXPECT_EQ( | |
747 conditions->minimum_battery_percentage, | |
748 coordinator()->policy()->BatteryPercentageRequired(!kUserRequested)); | |
749 EXPECT_EQ(conditions->require_unmetered_network, | |
750 coordinator()->policy()->UnmeteredNetworkRequired(!kUserRequested)); | |
751 } | |
752 | |
753 TEST_F(RequestCoordinatorTest, SchedulerGetsLeastRestrictiveConditions) { | |
754 // Put two requests on the queue - The first is user requested, and | |
755 // the second is not user requested. | |
756 AddRequest1(); | |
757 offline_pages::SavePageRequest request2(kRequestId2, kUrl2, kClientId2, | |
758 base::Time::Now(), !kUserRequested); | |
759 coordinator()->queue()->AddRequest( | |
760 request2, base::Bind(&RequestCoordinatorTest::AddRequestDone, | |
761 base::Unretained(this))); | |
762 PumpLoop(); | |
763 | |
764 // Trigger the scheduler to schedule for the least restrictive condition. | |
765 ScheduleForTest(); | |
766 PumpLoop(); | |
767 | |
768 // Expect that the scheduler got notified, and it is at user_requested | |
769 // priority. | |
770 SchedulerStub* scheduler_stub = | |
771 reinterpret_cast<SchedulerStub*>(coordinator()->scheduler()); | |
772 const Scheduler::TriggerConditions* conditions = scheduler_stub->conditions(); | |
773 EXPECT_TRUE(scheduler_stub->schedule_called()); | |
774 EXPECT_EQ(conditions->require_power_connected, | |
775 coordinator()->policy()->PowerRequired(kUserRequested)); | |
776 EXPECT_EQ(conditions->minimum_battery_percentage, | |
777 coordinator()->policy()->BatteryPercentageRequired(kUserRequested)); | |
778 EXPECT_EQ(conditions->require_unmetered_network, | |
779 coordinator()->policy()->UnmeteredNetworkRequired(kUserRequested)); | |
780 } | |
781 | |
782 TEST_F(RequestCoordinatorTest, StartProcessingWithLoadingDisabled) { | |
783 // Add a request to the queue, wait for callbacks to finish. | |
784 AddRequest1(); | |
785 PumpLoop(); | |
786 | |
787 DisableLoading(); | |
788 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
789 immediate_callback())); | |
790 | |
791 // Let the async callbacks in the request coordinator run. | |
792 PumpLoop(); | |
793 EXPECT_TRUE(immediate_schedule_callback_called()); | |
794 | |
795 EXPECT_FALSE(is_starting()); | |
796 EXPECT_EQ(Offliner::PRERENDERING_NOT_STARTED, last_offlining_status()); | |
797 } | |
798 | |
799 // This tests a StopProcessing call before we have actually started the | |
800 // prerenderer. | |
801 TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingImmediately) { | |
802 // Add a request to the queue, wait for callbacks to finish. | |
803 AddRequest1(); | |
804 PumpLoop(); | |
805 | |
806 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
807 immediate_callback())); | |
808 EXPECT_TRUE(is_starting()); | |
809 | |
810 // Now, quick, before it can do much (we haven't called PumpLoop), cancel it. | |
811 coordinator()->StopProcessing(Offliner::REQUEST_COORDINATOR_CANCELED); | |
812 | |
813 // Let the async callbacks in the request coordinator run. | |
814 PumpLoop(); | |
815 EXPECT_TRUE(immediate_schedule_callback_called()); | |
816 | |
817 EXPECT_FALSE(is_starting()); | |
818 | |
819 // OfflinerDoneCallback will not end up getting called with status SAVED, | |
820 // since we cancelled the event before it called offliner_->LoadAndSave(). | |
821 EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED, | |
822 last_offlining_status()); | |
823 | |
824 // Since offliner was not started, it will not have seen cancel call. | |
825 EXPECT_FALSE(OfflinerWasCanceled()); | |
826 } | |
827 | |
828 // This tests a StopProcessing call after the prerenderer has been started. | |
829 TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingLater) { | |
830 // Add a request to the queue, wait for callbacks to finish. | |
831 AddRequest1(); | |
832 PumpLoop(); | |
833 | |
834 // Ensure the start processing request stops before the completion callback. | |
835 EnableOfflinerCallback(false); | |
836 | |
837 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
838 immediate_callback())); | |
839 EXPECT_TRUE(is_starting()); | |
840 | |
841 // Let all the async parts of the start processing pipeline run to completion. | |
842 PumpLoop(); | |
843 | |
844 // Observer called for starting processing. | |
845 EXPECT_TRUE(observer().changed_called()); | |
846 EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state()); | |
847 observer().Clear(); | |
848 | |
849 // Since the offliner is disabled, this callback should not be called. | |
850 EXPECT_FALSE(immediate_schedule_callback_called()); | |
851 | |
852 // Coordinator should now be busy. | |
853 EXPECT_TRUE(is_busy()); | |
854 EXPECT_FALSE(is_starting()); | |
855 | |
856 // Now we cancel it while the prerenderer is busy. | |
857 coordinator()->StopProcessing(Offliner::REQUEST_COORDINATOR_CANCELED); | |
858 | |
859 // Let the async callbacks in the cancel run. | |
860 PumpLoop(); | |
861 | |
862 // Observer called for stopped processing. | |
863 EXPECT_TRUE(observer().changed_called()); | |
864 EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state()); | |
865 observer().Clear(); | |
866 | |
867 EXPECT_FALSE(is_busy()); | |
868 | |
869 // OfflinerDoneCallback will not end up getting called with status SAVED, | |
870 // since we cancelled the event before the LoadAndSave completed. | |
871 EXPECT_EQ(Offliner::RequestStatus::REQUEST_COORDINATOR_CANCELED, | |
872 last_offlining_status()); | |
873 | |
874 // Since offliner was started, it will have seen cancel call. | |
875 EXPECT_TRUE(OfflinerWasCanceled()); | |
876 } | |
877 | |
878 // This tests that canceling a request will result in TryNextRequest() getting | |
879 // called. | |
880 TEST_F(RequestCoordinatorTest, RemoveInflightRequest) { | |
881 // Add a request to the queue, wait for callbacks to finish. | |
882 AddRequest1(); | |
883 PumpLoop(); | |
884 | |
885 // Ensure the start processing request stops before the completion callback. | |
886 EnableOfflinerCallback(false); | |
887 | |
888 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions(), | |
889 immediate_callback())); | |
890 | |
891 // Let all the async parts of the start processing pipeline run to completion. | |
892 PumpLoop(); | |
893 // Since the offliner is disabled, this callback should not be called. | |
894 EXPECT_FALSE(immediate_schedule_callback_called()); | |
895 | |
896 // Remove the request while it is processing. | |
897 std::vector<int64_t> request_ids{kRequestId1}; | |
898 coordinator()->RemoveRequests( | |
899 request_ids, base::Bind(&RequestCoordinatorTest::RemoveRequestsDone, | |
900 base::Unretained(this))); | |
901 | |
902 // Let the async callbacks in the cancel run. | |
903 PumpLoop(); | |
904 | |
905 // Since offliner was started, it will have seen cancel call. | |
906 EXPECT_TRUE(OfflinerWasCanceled()); | |
907 } | |
908 | |
909 TEST_F(RequestCoordinatorTest, MarkRequestCompleted) { | |
910 int64_t request_id = coordinator()->SavePageLater( | |
911 kUrl1, kClientId1, kUserRequested, | |
912 RequestCoordinator::RequestAvailability::DISABLED_FOR_OFFLINER); | |
913 PumpLoop(); | |
914 EXPECT_NE(request_id, 0l); | |
915 | |
916 // Verify request added in OFFLINING state. | |
917 EXPECT_TRUE(observer().added_called()); | |
918 EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state()); | |
919 | |
920 // Call the method under test, making sure we send SUCCESS to the observer. | |
921 coordinator()->MarkRequestCompleted(request_id); | |
922 PumpLoop(); | |
923 | |
924 // Our observer should have seen SUCCESS instead of REMOVED. | |
925 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::SUCCESS, | |
926 observer().last_status()); | |
927 EXPECT_TRUE(observer().completed_called()); | |
928 } | |
929 | |
930 TEST_F(RequestCoordinatorTest, EnableForOffliner) { | |
931 // Pretend we are on low-end device so immediate start won't happen. | |
932 SetIsLowEndDeviceForTest(true); | |
933 | |
934 int64_t request_id = coordinator()->SavePageLater( | |
935 kUrl1, kClientId1, kUserRequested, | |
936 RequestCoordinator::RequestAvailability::DISABLED_FOR_OFFLINER); | |
937 PumpLoop(); | |
938 EXPECT_NE(request_id, 0l); | |
939 | |
940 // Verify request added and initial change to OFFLINING (in foreground). | |
941 EXPECT_TRUE(observer().added_called()); | |
942 EXPECT_TRUE(observer().changed_called()); | |
943 EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state()); | |
944 observer().Clear(); | |
945 | |
946 // Ensure that the new request does not finish so we can verify state change. | |
947 EnableOfflinerCallback(false); | |
948 | |
949 coordinator()->EnableForOffliner(request_id, kClientId1); | |
950 PumpLoop(); | |
951 | |
952 // Verify request changed again. | |
953 EXPECT_TRUE(observer().changed_called()); | |
954 EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state()); | |
955 } | |
956 | |
957 TEST_F(RequestCoordinatorTest, WatchdogTimeoutForScheduledProcessing) { | |
958 // Build a request to use with the pre-renderer, and put it on the queue. | |
959 offline_pages::SavePageRequest request( | |
960 kRequestId1, kUrl1, kClientId1, base::Time::Now(), kUserRequested); | |
961 // Set request to allow one more completed attempt. | |
962 int max_tries = coordinator()->policy()->GetMaxCompletedTries(); | |
963 request.set_completed_attempt_count(max_tries - 1); | |
964 coordinator()->queue()->AddRequest( | |
965 request, | |
966 base::Bind(&RequestCoordinatorTest::AddRequestDone, | |
967 base::Unretained(this))); | |
968 PumpLoop(); | |
969 | |
970 // Ensure that the new request does not finish - we simulate it being | |
971 // in progress by asking it to skip making the completion callback. | |
972 EnableOfflinerCallback(false); | |
973 | |
974 // Sending the request to the offliner. | |
975 EXPECT_TRUE( | |
976 coordinator()->StartProcessing(device_conditions(), waiting_callback())); | |
977 PumpLoop(); | |
978 | |
979 // Advance the mock clock far enough to cause a watchdog timeout | |
980 AdvanceClockBy(base::TimeDelta::FromSeconds( | |
981 coordinator() | |
982 ->policy() | |
983 ->GetSinglePageTimeLimitWhenBackgroundScheduledInSeconds() + 1)); | |
984 PumpLoop(); | |
985 | |
986 // Wait for timeout to expire. Use a TaskRunner with a DelayedTaskRunner | |
987 // which won't time out immediately, so the watchdog thread doesn't kill valid | |
988 // tasks too soon. | |
989 WaitForCallback(); | |
990 PumpLoop(); | |
991 | |
992 EXPECT_FALSE(is_starting()); | |
993 EXPECT_FALSE(coordinator()->is_busy()); | |
994 EXPECT_TRUE(OfflinerWasCanceled()); | |
995 } | |
996 | |
997 TEST_F(RequestCoordinatorTest, WatchdogTimeoutForImmediateProcessing) { | |
998 // If low end device, pretend it is not so that immediate start happens. | |
999 SetIsLowEndDeviceForTest(false); | |
1000 | |
1001 // Ensure that the new request does not finish - we simulate it being | |
1002 // in progress by asking it to skip making the completion callback. | |
1003 EnableOfflinerCallback(false); | |
1004 | |
1005 EXPECT_NE( | |
1006 coordinator()->SavePageLater( | |
1007 kUrl1, kClientId1, kUserRequested, | |
1008 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
1009 PumpLoop(); | |
1010 | |
1011 // Verify that immediate start from adding the request did happen. | |
1012 EXPECT_TRUE(coordinator()->is_busy()); | |
1013 | |
1014 // Advance the mock clock 1 second before the watchdog timeout. | |
1015 AdvanceClockBy(base::TimeDelta::FromSeconds( | |
1016 coordinator() | |
1017 ->policy() | |
1018 ->GetSinglePageTimeLimitForImmediateLoadInSeconds() - 1)); | |
1019 PumpLoop(); | |
1020 | |
1021 // Verify still busy. | |
1022 EXPECT_TRUE(coordinator()->is_busy()); | |
1023 EXPECT_FALSE(OfflinerWasCanceled()); | |
1024 | |
1025 // Advance the mock clock past the watchdog timeout now. | |
1026 AdvanceClockBy(base::TimeDelta::FromSeconds(2)); | |
1027 PumpLoop(); | |
1028 | |
1029 // Verify the request timed out. | |
1030 EXPECT_TRUE(OfflinerWasCanceled()); | |
1031 } | |
1032 | |
1033 TEST_F(RequestCoordinatorTest, TimeBudgetExceeded) { | |
1034 EnableOfflinerCallback(false); | |
1035 // Build two requests to use with the pre-renderer, and put it on the queue. | |
1036 AddRequest1(); | |
1037 // The second request will have a larger completed attempt count. | |
1038 offline_pages::SavePageRequest request2(kRequestId1 + 1, kUrl1, kClientId1, | |
1039 base::Time::Now(), kUserRequested); | |
1040 request2.set_completed_attempt_count(kAttemptCount); | |
1041 coordinator()->queue()->AddRequest( | |
1042 request2, base::Bind(&RequestCoordinatorTest::AddRequestDone, | |
1043 base::Unretained(this))); | |
1044 PumpLoop(); | |
1045 | |
1046 // Sending the request to the offliner. | |
1047 EXPECT_TRUE( | |
1048 coordinator()->StartProcessing(device_conditions(), waiting_callback())); | |
1049 PumpLoop(); | |
1050 | |
1051 // Advance the mock clock far enough to exceed our time budget. | |
1052 // The first request will time out, and because we are over time budget, | |
1053 // the second request will not be started. | |
1054 AdvanceClockBy(base::TimeDelta::FromSeconds(kTestTimeBudgetSeconds)); | |
1055 PumpLoop(); | |
1056 | |
1057 // TryNextRequest should decide that there is no more work to be done, | |
1058 // and call back to the scheduler, even though there is another request in the | |
1059 // queue. Both requests should be left in the queue. | |
1060 coordinator()->queue()->GetRequests( | |
1061 base::Bind(&RequestCoordinatorTest::GetRequestsDone, | |
1062 base::Unretained(this))); | |
1063 PumpLoop(); | |
1064 | |
1065 // We should find two requests in the queue. | |
1066 // The first request should now have a completed count of 1. | |
1067 EXPECT_EQ(2UL, last_requests().size()); | |
1068 EXPECT_EQ(1L, last_requests().at(0)->completed_attempt_count()); | |
1069 } | |
1070 | |
1071 TEST_F(RequestCoordinatorTest, TryNextRequestWithNoNetwork) { | |
1072 SavePageRequest request1 = AddRequest1(); | |
1073 AddRequest2(); | |
1074 PumpLoop(); | |
1075 | |
1076 // Set up for the call to StartProcessing. | |
1077 EnableOfflinerCallback(false); | |
1078 | |
1079 // Sending the request to the offliner. | |
1080 EXPECT_TRUE( | |
1081 coordinator()->StartProcessing(device_conditions(), waiting_callback())); | |
1082 PumpLoop(); | |
1083 EXPECT_TRUE(coordinator()->is_busy()); | |
1084 | |
1085 // Now lose the network connection. | |
1086 SetNetworkConnected(false); | |
1087 | |
1088 // Complete first request and then TryNextRequest should decide not | |
1089 // to pick another request (because of no network connection). | |
1090 SendOfflinerDoneCallback(request1, Offliner::RequestStatus::SAVED); | |
1091 PumpLoop(); | |
1092 | |
1093 // Not starting nor busy with next request. | |
1094 EXPECT_FALSE(coordinator()->is_starting()); | |
1095 EXPECT_FALSE(coordinator()->is_busy()); | |
1096 | |
1097 // Get queued requests. | |
1098 coordinator()->queue()->GetRequests(base::Bind( | |
1099 &RequestCoordinatorTest::GetRequestsDone, base::Unretained(this))); | |
1100 PumpLoop(); | |
1101 | |
1102 // We should find one request in the queue. | |
1103 EXPECT_EQ(1UL, last_requests().size()); | |
1104 } | |
1105 | |
1106 TEST_F(RequestCoordinatorTest, GetAllRequests) { | |
1107 // Add two requests to the queue. | |
1108 AddRequest1(); | |
1109 AddRequest2(); | |
1110 PumpLoop(); | |
1111 | |
1112 // Start the async status fetching. | |
1113 coordinator()->GetAllRequests(base::Bind( | |
1114 &RequestCoordinatorTest::GetQueuedRequestsDone, base::Unretained(this))); | |
1115 PumpLoop(); | |
1116 | |
1117 // Wait for async get to finish. | |
1118 WaitForCallback(); | |
1119 PumpLoop(); | |
1120 | |
1121 // Check that the statuses found in the callback match what we expect. | |
1122 EXPECT_EQ(2UL, last_requests().size()); | |
1123 EXPECT_EQ(kRequestId1, last_requests().at(0)->request_id()); | |
1124 EXPECT_EQ(kRequestId2, last_requests().at(1)->request_id()); | |
1125 } | |
1126 | |
1127 #if defined(OS_IOS) | |
1128 // Flaky on IOS. http://crbug/663311 | |
1129 #define MAYBE_PauseAndResumeObserver DISABLED_PauseAndResumeObserver | |
1130 #else | |
1131 #define MAYBE_PauseAndResumeObserver PauseAndResumeObserver | |
1132 #endif | |
1133 TEST_F(RequestCoordinatorTest, MAYBE_PauseAndResumeObserver) { | |
1134 // Add a request to the queue. | |
1135 AddRequest1(); | |
1136 PumpLoop(); | |
1137 | |
1138 // Pause the request. | |
1139 std::vector<int64_t> request_ids; | |
1140 request_ids.push_back(kRequestId1); | |
1141 coordinator()->PauseRequests(request_ids); | |
1142 PumpLoop(); | |
1143 | |
1144 EXPECT_TRUE(observer().changed_called()); | |
1145 EXPECT_EQ(SavePageRequest::RequestState::PAUSED, observer().state()); | |
1146 | |
1147 // Clear out the observer before the next call. | |
1148 observer().Clear(); | |
1149 | |
1150 // Resume the request. | |
1151 coordinator()->ResumeRequests(request_ids); | |
1152 PumpLoop(); | |
1153 | |
1154 EXPECT_TRUE(observer().changed_called()); | |
1155 | |
1156 // Now whether request is offlining or just available depends on whether test | |
1157 // is run on svelte device or not. | |
1158 if (base::SysInfo::IsLowEndDevice()) { | |
1159 EXPECT_EQ(SavePageRequest::RequestState::AVAILABLE, observer().state()); | |
1160 } else { | |
1161 EXPECT_EQ(SavePageRequest::RequestState::OFFLINING, observer().state()); | |
1162 } | |
1163 } | |
1164 | |
1165 TEST_F(RequestCoordinatorTest, RemoveRequest) { | |
1166 // Add a request to the queue. | |
1167 AddRequest1(); | |
1168 PumpLoop(); | |
1169 | |
1170 // Remove the request. | |
1171 std::vector<int64_t> request_ids; | |
1172 request_ids.push_back(kRequestId1); | |
1173 coordinator()->RemoveRequests( | |
1174 request_ids, base::Bind(&RequestCoordinatorTest::RemoveRequestsDone, | |
1175 base::Unretained(this))); | |
1176 | |
1177 PumpLoop(); | |
1178 WaitForCallback(); | |
1179 PumpLoop(); | |
1180 | |
1181 EXPECT_TRUE(observer().completed_called()); | |
1182 EXPECT_EQ(RequestCoordinator::BackgroundSavePageResult::REMOVED, | |
1183 observer().last_status()); | |
1184 EXPECT_EQ(1UL, last_remove_results().size()); | |
1185 EXPECT_EQ(kRequestId1, std::get<0>(last_remove_results().at(0))); | |
1186 } | |
1187 | |
1188 TEST_F(RequestCoordinatorTest, | |
1189 SavePageStartsProcessingWhenConnectedAndNotLowEndDevice) { | |
1190 // Turn off the callback so that the request stops before processing in | |
1191 // PumpLoop. | |
1192 EnableOfflinerCallback(false); | |
1193 EXPECT_NE( | |
1194 coordinator()->SavePageLater( | |
1195 kUrl1, kClientId1, kUserRequested, | |
1196 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
1197 PumpLoop(); | |
1198 | |
1199 // Now whether processing triggered immediately depends on whether test | |
1200 // is run on svelte device or not. | |
1201 if (base::SysInfo::IsLowEndDevice()) { | |
1202 EXPECT_FALSE(is_busy()); | |
1203 } else { | |
1204 EXPECT_TRUE(is_busy()); | |
1205 } | |
1206 } | |
1207 | |
1208 TEST_F(RequestCoordinatorTest, | |
1209 SavePageStartsProcessingWhenConnectedOnLowEndDeviceIfFlagEnabled) { | |
1210 // Mark device as low-end device. | |
1211 SetIsLowEndDeviceForTest(true); | |
1212 EXPECT_FALSE(offline_pages::IsOfflinePagesSvelteConcurrentLoadingEnabled()); | |
1213 | |
1214 // Make a request. | |
1215 EXPECT_NE(coordinator()->SavePageLater( | |
1216 kUrl1, kClientId1, kUserRequested, | |
1217 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), | |
1218 0); | |
1219 PumpLoop(); | |
1220 | |
1221 // Verify not immediately busy (since low-end device). | |
1222 EXPECT_FALSE(is_busy()); | |
1223 | |
1224 // Set feature flag to allow concurrent loads. | |
1225 base::test::ScopedFeatureList scoped_feature_list; | |
1226 scoped_feature_list.InitAndEnableFeature( | |
1227 kOfflinePagesSvelteConcurrentLoadingFeature); | |
1228 EXPECT_TRUE(offline_pages::IsOfflinePagesSvelteConcurrentLoadingEnabled()); | |
1229 | |
1230 // Turn off the callback so that the request stops before processing in | |
1231 // PumpLoop. | |
1232 EnableOfflinerCallback(false); | |
1233 | |
1234 // Make another request. | |
1235 EXPECT_NE(coordinator()->SavePageLater( | |
1236 kUrl2, kClientId2, kUserRequested, | |
1237 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), | |
1238 0); | |
1239 PumpLoop(); | |
1240 | |
1241 // Verify immediate processing did start this time. | |
1242 EXPECT_TRUE(is_busy()); | |
1243 } | |
1244 | |
1245 TEST_F(RequestCoordinatorTest, SavePageDoesntStartProcessingWhenDisconnected) { | |
1246 SetNetworkConnected(false); | |
1247 EXPECT_NE( | |
1248 coordinator()->SavePageLater( | |
1249 kUrl1, kClientId1, kUserRequested, | |
1250 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
1251 PumpLoop(); | |
1252 EXPECT_FALSE(is_busy()); | |
1253 } | |
1254 | |
1255 TEST_F(RequestCoordinatorTest, | |
1256 SavePageDoesStartProcessingWhenPoorlyConnected) { | |
1257 // Set specific network type for 2G with poor effective connection. | |
1258 SetNetworkConditionsForTest( | |
1259 net::NetworkChangeNotifier::ConnectionType::CONNECTION_2G); | |
1260 SetEffectiveConnectionTypeForTest( | |
1261 net::EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_SLOW_2G); | |
1262 | |
1263 // Turn off the callback so that the request stops before processing in | |
1264 // PumpLoop. | |
1265 EnableOfflinerCallback(false); | |
1266 | |
1267 EXPECT_NE( | |
1268 coordinator()->SavePageLater( | |
1269 kUrl1, kClientId1, kUserRequested, | |
1270 RequestCoordinator::RequestAvailability::ENABLED_FOR_OFFLINER), 0); | |
1271 PumpLoop(); | |
1272 EXPECT_TRUE(is_busy()); | |
1273 } | |
1274 | |
1275 TEST_F(RequestCoordinatorTest, | |
1276 ResumeStartsProcessingWhenConnectedAndNotLowEndDevice) { | |
1277 // Start unconnected. | |
1278 SetNetworkConnected(false); | |
1279 | |
1280 // Turn off the callback so that the request stops before processing in | |
1281 // PumpLoop. | |
1282 EnableOfflinerCallback(false); | |
1283 | |
1284 // Add a request to the queue. | |
1285 AddRequest1(); | |
1286 PumpLoop(); | |
1287 EXPECT_FALSE(is_busy()); | |
1288 | |
1289 // Pause the request. | |
1290 std::vector<int64_t> request_ids; | |
1291 request_ids.push_back(kRequestId1); | |
1292 coordinator()->PauseRequests(request_ids); | |
1293 PumpLoop(); | |
1294 | |
1295 // Resume the request while disconnected. | |
1296 coordinator()->ResumeRequests(request_ids); | |
1297 PumpLoop(); | |
1298 EXPECT_FALSE(is_busy()); | |
1299 | |
1300 // Pause the request again. | |
1301 coordinator()->PauseRequests(request_ids); | |
1302 PumpLoop(); | |
1303 | |
1304 // Now simulate reasonable connection. | |
1305 SetNetworkConnected(true); | |
1306 | |
1307 // Resume the request while connected. | |
1308 coordinator()->ResumeRequests(request_ids); | |
1309 EXPECT_FALSE(is_busy()); | |
1310 PumpLoop(); | |
1311 | |
1312 // Now whether processing triggered immediately depends on whether test | |
1313 // is run on svelte device or not. | |
1314 if (base::SysInfo::IsLowEndDevice()) { | |
1315 EXPECT_FALSE(is_busy()); | |
1316 } else { | |
1317 EXPECT_TRUE(is_busy()); | |
1318 } | |
1319 } | |
1320 | |
1321 } // namespace offline_pages | |
OLD | NEW |