OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/offline_pages/background/request_coordinator.h" | 5 #include "components/offline_pages/background/request_coordinator.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 bool schedule_called() const { return schedule_called_; } | 47 bool schedule_called() const { return schedule_called_; } |
48 | 48 |
49 bool unschedule_called() const { return unschedule_called_; } | 49 bool unschedule_called() const { return unschedule_called_; } |
50 | 50 |
51 private: | 51 private: |
52 bool schedule_called_; | 52 bool schedule_called_; |
53 bool unschedule_called_; | 53 bool unschedule_called_; |
54 }; | 54 }; |
55 | 55 |
56 class OfflinerStub : public Offliner { | 56 class OfflinerStub : public Offliner { |
| 57 |
| 58 public: |
| 59 OfflinerStub() : request_(kRequestId, kUrl, kClientId, base::Time::Now()), |
| 60 skip_callback_(false) {} |
| 61 |
57 bool LoadAndSave(const SavePageRequest& request, | 62 bool LoadAndSave(const SavePageRequest& request, |
58 const CompletionCallback& callback) override { | 63 const CompletionCallback& callback) override { |
| 64 callback_ = callback; |
| 65 request_ = request; |
| 66 // Post the callback on the run loop. |
| 67 if (!skip_callback_) { |
| 68 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 69 FROM_HERE, |
| 70 base::Bind(callback, request, Offliner::RequestStatus::SAVED)); |
| 71 } |
| 72 return true; |
| 73 } |
| 74 |
| 75 void set_skip_callback(bool skip) { |
| 76 skip_callback_ = skip; |
| 77 } |
| 78 |
| 79 // Clears the currently processing request, if any. Must have called |
| 80 // LoadAndSave first to set the callback and request. |
| 81 void Cancel() override { |
59 // Post the callback on the run loop. | 82 // Post the callback on the run loop. |
60 base::ThreadTaskRunnerHandle::Get()->PostTask( | 83 base::ThreadTaskRunnerHandle::Get()->PostTask( |
61 FROM_HERE, | 84 FROM_HERE, |
62 base::Bind(callback, request, Offliner::RequestStatus::SAVED)); | 85 base::Bind(callback_, request_, Offliner::RequestStatus::CANCELED)); |
63 return true; | |
64 } | 86 } |
65 | 87 |
66 // Clears the currently processing request, if any. | 88 private: |
67 void Cancel() override {} | 89 CompletionCallback callback_; |
| 90 SavePageRequest request_; |
| 91 bool skip_callback_; |
68 }; | 92 }; |
69 | 93 |
70 class OfflinerFactoryStub : public OfflinerFactory { | 94 class OfflinerFactoryStub : public OfflinerFactory { |
71 public: | 95 public: |
| 96 |
| 97 OfflinerFactoryStub() : offliner_(nullptr) {} |
| 98 |
72 Offliner* GetOffliner(const OfflinerPolicy* policy) override { | 99 Offliner* GetOffliner(const OfflinerPolicy* policy) override { |
73 offliner_.reset(new OfflinerStub()); | 100 if (offliner_.get() == nullptr) { |
| 101 offliner_.reset(new OfflinerStub()); |
| 102 } |
74 return offliner_.get(); | 103 return offliner_.get(); |
75 } | 104 } |
76 | 105 |
77 private: | 106 private: |
78 std::unique_ptr<Offliner> offliner_; | 107 std::unique_ptr<OfflinerStub> offliner_; |
79 }; | 108 }; |
80 | 109 |
81 class RequestCoordinatorTest | 110 class RequestCoordinatorTest |
82 : public testing::Test { | 111 : public testing::Test { |
83 public: | 112 public: |
84 RequestCoordinatorTest(); | 113 RequestCoordinatorTest(); |
85 ~RequestCoordinatorTest() override; | 114 ~RequestCoordinatorTest() override; |
86 | 115 |
87 void SetUp() override; | 116 void SetUp() override; |
88 | 117 |
(...skipping 19 matching lines...) Expand all Loading... |
108 Offliner::RequestStatus status); | 137 Offliner::RequestStatus status); |
109 | 138 |
110 RequestQueue::GetRequestsResult last_get_requests_result() const { | 139 RequestQueue::GetRequestsResult last_get_requests_result() const { |
111 return last_get_requests_result_; | 140 return last_get_requests_result_; |
112 } | 141 } |
113 | 142 |
114 const std::vector<SavePageRequest>& last_requests() const { | 143 const std::vector<SavePageRequest>& last_requests() const { |
115 return last_requests_; | 144 return last_requests_; |
116 } | 145 } |
117 | 146 |
| 147 Offliner::RequestStatus last_offlining_status() const { |
| 148 return coordinator_->last_offlining_status_; |
| 149 } |
| 150 |
| 151 void SkipOfflinerCallback() { |
| 152 offliner_->set_skip_callback(true); |
| 153 } |
| 154 |
118 private: | 155 private: |
119 RequestQueue::GetRequestsResult last_get_requests_result_; | 156 RequestQueue::GetRequestsResult last_get_requests_result_; |
120 std::vector<SavePageRequest> last_requests_; | 157 std::vector<SavePageRequest> last_requests_; |
121 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; | 158 scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
122 base::ThreadTaskRunnerHandle task_runner_handle_; | 159 base::ThreadTaskRunnerHandle task_runner_handle_; |
123 std::unique_ptr<RequestCoordinator> coordinator_; | 160 std::unique_ptr<RequestCoordinator> coordinator_; |
| 161 OfflinerStub* offliner_; |
124 }; | 162 }; |
125 | 163 |
126 RequestCoordinatorTest::RequestCoordinatorTest() | 164 RequestCoordinatorTest::RequestCoordinatorTest() |
127 : last_get_requests_result_(RequestQueue::GetRequestsResult::STORE_FAILURE), | 165 : last_get_requests_result_(RequestQueue::GetRequestsResult::STORE_FAILURE), |
128 task_runner_(new base::TestSimpleTaskRunner), | 166 task_runner_(new base::TestSimpleTaskRunner), |
129 task_runner_handle_(task_runner_) {} | 167 task_runner_handle_(task_runner_), |
| 168 offliner_(nullptr) {} |
130 | 169 |
131 RequestCoordinatorTest::~RequestCoordinatorTest() {} | 170 RequestCoordinatorTest::~RequestCoordinatorTest() {} |
132 | 171 |
133 void RequestCoordinatorTest::SetUp() { | 172 void RequestCoordinatorTest::SetUp() { |
134 std::unique_ptr<OfflinerPolicy> policy(new OfflinerPolicy()); | 173 std::unique_ptr<OfflinerPolicy> policy(new OfflinerPolicy()); |
135 std::unique_ptr<OfflinerFactory> factory(new OfflinerFactoryStub()); | 174 std::unique_ptr<OfflinerFactory> factory(new OfflinerFactoryStub()); |
| 175 // Save the offliner for use by the tests. |
| 176 offliner_ = |
| 177 reinterpret_cast<OfflinerStub*>(factory->GetOffliner(policy.get())); |
136 std::unique_ptr<RequestQueueInMemoryStore> | 178 std::unique_ptr<RequestQueueInMemoryStore> |
137 store(new RequestQueueInMemoryStore()); | 179 store(new RequestQueueInMemoryStore()); |
138 std::unique_ptr<RequestQueue> queue(new RequestQueue(std::move(store))); | 180 std::unique_ptr<RequestQueue> queue(new RequestQueue(std::move(store))); |
139 std::unique_ptr<Scheduler> scheduler_stub(new SchedulerStub()); | 181 std::unique_ptr<Scheduler> scheduler_stub(new SchedulerStub()); |
140 coordinator_.reset(new RequestCoordinator( | 182 coordinator_.reset(new RequestCoordinator( |
141 std::move(policy), std::move(factory), std::move(queue), | 183 std::move(policy), std::move(factory), std::move(queue), |
142 std::move(scheduler_stub))); | 184 std::move(scheduler_stub))); |
143 } | 185 } |
144 | 186 |
145 void RequestCoordinatorTest::PumpLoop() { | 187 void RequestCoordinatorTest::PumpLoop() { |
146 task_runner_->RunUntilIdle(); | 188 task_runner_->RunUntilIdle(); |
147 } | 189 } |
148 | 190 |
149 void RequestCoordinatorTest::GetRequestsDone( | 191 void RequestCoordinatorTest::GetRequestsDone( |
150 RequestQueue::GetRequestsResult result, | 192 RequestQueue::GetRequestsResult result, |
151 const std::vector<SavePageRequest>& requests) { | 193 const std::vector<SavePageRequest>& requests) { |
152 last_get_requests_result_ = result; | 194 last_get_requests_result_ = result; |
153 last_requests_ = requests; | 195 last_requests_ = requests; |
154 } | 196 } |
155 | 197 |
156 | |
157 void RequestCoordinatorTest::AddRequestDone( | 198 void RequestCoordinatorTest::AddRequestDone( |
158 RequestQueue::AddRequestResult result, | 199 RequestQueue::AddRequestResult result, |
159 const SavePageRequest& request) {} | 200 const SavePageRequest& request) {} |
160 | 201 |
161 void RequestCoordinatorTest::SendOfflinerDoneCallback( | 202 void RequestCoordinatorTest::SendOfflinerDoneCallback( |
162 const SavePageRequest& request, Offliner::RequestStatus status) { | 203 const SavePageRequest& request, Offliner::RequestStatus status) { |
163 // Using the fact that the test class is a friend, call to the callback | 204 // Using the fact that the test class is a friend, call to the callback |
164 coordinator_->OfflinerDoneCallback(request, status); | 205 coordinator_->OfflinerDoneCallback(request, status); |
165 } | 206 } |
166 | 207 |
167 | |
168 TEST_F(RequestCoordinatorTest, StartProcessingWithNoRequests) { | 208 TEST_F(RequestCoordinatorTest, StartProcessingWithNoRequests) { |
169 DeviceConditions device_conditions(false, 75, | 209 DeviceConditions device_conditions(false, 75, |
170 net::NetworkChangeNotifier::CONNECTION_3G); | 210 net::NetworkChangeNotifier::CONNECTION_3G); |
171 base::Callback<void(bool)> callback = | 211 base::Callback<void(bool)> callback = |
172 base::Bind( | 212 base::Bind( |
173 &RequestCoordinatorTest::EmptyCallbackFunction, | 213 &RequestCoordinatorTest::EmptyCallbackFunction, |
174 base::Unretained(this)); | 214 base::Unretained(this)); |
175 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions, callback)); | 215 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions, callback)); |
176 } | 216 } |
177 | 217 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 coordinator()->queue()->GetRequests( | 297 coordinator()->queue()->GetRequests( |
258 base::Bind(&RequestCoordinatorTest::GetRequestsDone, | 298 base::Bind(&RequestCoordinatorTest::GetRequestsDone, |
259 base::Unretained(this))); | 299 base::Unretained(this))); |
260 PumpLoop(); | 300 PumpLoop(); |
261 | 301 |
262 // Still one request in the queue. | 302 // Still one request in the queue. |
263 EXPECT_EQ(1UL, last_requests().size()); | 303 EXPECT_EQ(1UL, last_requests().size()); |
264 // TODO(dougarnett): Verify retry count gets incremented. | 304 // TODO(dougarnett): Verify retry count gets incremented. |
265 } | 305 } |
266 | 306 |
| 307 // This tests a StopProcessing call before we have actually started the |
| 308 // prerenderer. |
| 309 TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingImmediately) { |
| 310 // Add a request to the queue, wait for callbacks to finish. |
| 311 offline_pages::SavePageRequest request( |
| 312 kRequestId, kUrl, kClientId, base::Time::Now()); |
| 313 coordinator()->queue()->AddRequest( |
| 314 request, |
| 315 base::Bind(&RequestCoordinatorTest::AddRequestDone, |
| 316 base::Unretained(this))); |
| 317 PumpLoop(); |
| 318 |
| 319 DeviceConditions device_conditions(false, 75, |
| 320 net::NetworkChangeNotifier::CONNECTION_3G); |
| 321 base::Callback<void(bool)> callback = |
| 322 base::Bind( |
| 323 &RequestCoordinatorTest::EmptyCallbackFunction, |
| 324 base::Unretained(this)); |
| 325 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions, callback)); |
| 326 |
| 327 // Now, quick, before it can do much (we haven't called PumpLoop), cancel it. |
| 328 coordinator()->StopProcessing(); |
| 329 |
| 330 // Let the async callbacks in the request coordinator run. |
| 331 PumpLoop(); |
| 332 |
| 333 // OfflinerDoneCallback will not end up getting called with status SAVED, |
| 334 // Since we cancelled the event before it called offliner_->LoadAndSave(). |
| 335 EXPECT_NE(Offliner::RequestStatus::SAVED, last_offlining_status()); |
| 336 } |
| 337 |
| 338 // This tests a StopProcessing call after the prerenderer has been started. |
| 339 TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingLater) { |
| 340 // Add a request to the queue, wait for callbacks to finish. |
| 341 offline_pages::SavePageRequest request( |
| 342 kRequestId, kUrl, kClientId, base::Time::Now()); |
| 343 coordinator()->queue()->AddRequest( |
| 344 request, |
| 345 base::Bind(&RequestCoordinatorTest::AddRequestDone, |
| 346 base::Unretained(this))); |
| 347 PumpLoop(); |
| 348 |
| 349 // Ensure the start processing request stops before the completion callback. |
| 350 SkipOfflinerCallback(); |
| 351 |
| 352 DeviceConditions device_conditions(false, 75, |
| 353 net::NetworkChangeNotifier::CONNECTION_3G); |
| 354 base::Callback<void(bool)> callback = |
| 355 base::Bind( |
| 356 &RequestCoordinatorTest::EmptyCallbackFunction, |
| 357 base::Unretained(this)); |
| 358 EXPECT_TRUE(coordinator()->StartProcessing(device_conditions, callback)); |
| 359 |
| 360 // Let all the async parts of the start processing pipeline run to completion. |
| 361 PumpLoop(); |
| 362 |
| 363 // Now we cancel it while the prerenderer is busy. |
| 364 coordinator()->StopProcessing(); |
| 365 |
| 366 // Let the async callbacks in the cancel run. |
| 367 PumpLoop(); |
| 368 |
| 369 // OfflinerDoneCallback will not end up getting called with status SAVED, |
| 370 // Since we cancelled the event before it called offliner_->LoadAndSave(). |
| 371 EXPECT_EQ(Offliner::RequestStatus::CANCELED, last_offlining_status()); |
| 372 } |
| 373 |
267 } // namespace offline_pages | 374 } // namespace offline_pages |
OLD | NEW |