Index: components/offline_pages/background/request_coordinator_unittest.cc |
diff --git a/components/offline_pages/background/request_coordinator_unittest.cc b/components/offline_pages/background/request_coordinator_unittest.cc |
index ebcbe140f39a7b3f1a30b8ffbf8e619d52ed20f4..faeef3d215e0f999f2fe6816f72cc4e82d4e0750 100644 |
--- a/components/offline_pages/background/request_coordinator_unittest.cc |
+++ b/components/offline_pages/background/request_coordinator_unittest.cc |
@@ -54,28 +54,57 @@ class SchedulerStub : public Scheduler { |
}; |
class OfflinerStub : public Offliner { |
+ |
+ public: |
+ OfflinerStub() : request_(kRequestId, kUrl, kClientId, base::Time::Now()), |
+ skip_callback_(false) {} |
+ |
bool LoadAndSave(const SavePageRequest& request, |
const CompletionCallback& callback) override { |
+ callback_ = callback; |
+ request_ = request; |
+ // Post the callback on the run loop. |
+ if (!skip_callback_) { |
+ base::ThreadTaskRunnerHandle::Get()->PostTask( |
+ FROM_HERE, |
+ base::Bind(callback, request, Offliner::RequestStatus::SAVED)); |
+ } |
+ return true; |
+ } |
+ |
+ void set_skip_callback(bool skip) { |
+ skip_callback_ = skip; |
+ } |
+ |
+ // Clears the currently processing request, if any. Must have called |
+ // LoadAndSave first to set the callback and request. |
+ void Cancel() override { |
// Post the callback on the run loop. |
base::ThreadTaskRunnerHandle::Get()->PostTask( |
FROM_HERE, |
- base::Bind(callback, request, Offliner::RequestStatus::SAVED)); |
- return true; |
+ base::Bind(callback_, request_, Offliner::RequestStatus::CANCELED)); |
} |
- // Clears the currently processing request, if any. |
- void Cancel() override {} |
+ private: |
+ CompletionCallback callback_; |
+ SavePageRequest request_; |
+ bool skip_callback_; |
}; |
class OfflinerFactoryStub : public OfflinerFactory { |
public: |
+ |
+ OfflinerFactoryStub() : offliner_(nullptr) {} |
+ |
Offliner* GetOffliner(const OfflinerPolicy* policy) override { |
- offliner_.reset(new OfflinerStub()); |
+ if (offliner_.get() == nullptr) { |
+ offliner_.reset(new OfflinerStub()); |
+ } |
return offliner_.get(); |
} |
private: |
- std::unique_ptr<Offliner> offliner_; |
+ std::unique_ptr<OfflinerStub> offliner_; |
}; |
class RequestCoordinatorTest |
@@ -115,24 +144,37 @@ class RequestCoordinatorTest |
return last_requests_; |
} |
+ Offliner::RequestStatus last_offlining_status() const { |
+ return coordinator_->last_offlining_status_; |
+ } |
+ |
+ void SkipOfflinerCallback() { |
+ offliner_->set_skip_callback(true); |
+ } |
+ |
private: |
RequestQueue::GetRequestsResult last_get_requests_result_; |
std::vector<SavePageRequest> last_requests_; |
scoped_refptr<base::TestSimpleTaskRunner> task_runner_; |
base::ThreadTaskRunnerHandle task_runner_handle_; |
std::unique_ptr<RequestCoordinator> coordinator_; |
+ OfflinerStub* offliner_; |
}; |
RequestCoordinatorTest::RequestCoordinatorTest() |
: last_get_requests_result_(RequestQueue::GetRequestsResult::STORE_FAILURE), |
task_runner_(new base::TestSimpleTaskRunner), |
- task_runner_handle_(task_runner_) {} |
+ task_runner_handle_(task_runner_), |
+ offliner_(nullptr) {} |
RequestCoordinatorTest::~RequestCoordinatorTest() {} |
void RequestCoordinatorTest::SetUp() { |
std::unique_ptr<OfflinerPolicy> policy(new OfflinerPolicy()); |
std::unique_ptr<OfflinerFactory> factory(new OfflinerFactoryStub()); |
+ // Save the offliner for use by the tests. |
+ offliner_ = |
+ reinterpret_cast<OfflinerStub*>(factory->GetOffliner(policy.get())); |
std::unique_ptr<RequestQueueInMemoryStore> |
store(new RequestQueueInMemoryStore()); |
std::unique_ptr<RequestQueue> queue(new RequestQueue(std::move(store))); |
@@ -153,7 +195,6 @@ void RequestCoordinatorTest::GetRequestsDone( |
last_requests_ = requests; |
} |
- |
void RequestCoordinatorTest::AddRequestDone( |
RequestQueue::AddRequestResult result, |
const SavePageRequest& request) {} |
@@ -164,7 +205,6 @@ void RequestCoordinatorTest::SendOfflinerDoneCallback( |
coordinator_->OfflinerDoneCallback(request, status); |
} |
- |
TEST_F(RequestCoordinatorTest, StartProcessingWithNoRequests) { |
DeviceConditions device_conditions(false, 75, |
net::NetworkChangeNotifier::CONNECTION_3G); |
@@ -264,4 +304,71 @@ TEST_F(RequestCoordinatorTest, OfflinerDoneRequestFailed) { |
// TODO(dougarnett): Verify retry count gets incremented. |
} |
+// This tests a StopProcessing call before we have actually started the |
+// prerenderer. |
+TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingImmediately) { |
+ // Add a request to the queue, wait for callbacks to finish. |
+ offline_pages::SavePageRequest request( |
+ kRequestId, kUrl, kClientId, base::Time::Now()); |
+ coordinator()->queue()->AddRequest( |
+ request, |
+ base::Bind(&RequestCoordinatorTest::AddRequestDone, |
+ base::Unretained(this))); |
+ PumpLoop(); |
+ |
+ DeviceConditions device_conditions(false, 75, |
+ net::NetworkChangeNotifier::CONNECTION_3G); |
+ base::Callback<void(bool)> callback = |
+ base::Bind( |
+ &RequestCoordinatorTest::EmptyCallbackFunction, |
+ base::Unretained(this)); |
+ EXPECT_TRUE(coordinator()->StartProcessing(device_conditions, callback)); |
+ |
+ // Now, quick, before it can do much (we haven't called PumpLoop), cancel it. |
+ coordinator()->StopProcessing(); |
+ |
+ // Let the async callbacks in the request coordinator run. |
+ PumpLoop(); |
+ |
+ // OfflinerDoneCallback will not end up getting called with status SAVED, |
+ // Since we cancelled the event before it called offliner_->LoadAndSave(). |
+ EXPECT_NE(Offliner::RequestStatus::SAVED, last_offlining_status()); |
+} |
+ |
+// This tests a StopProcessing call after the prerenderer has been started. |
+TEST_F(RequestCoordinatorTest, StartProcessingThenStopProcessingLater) { |
+ // Add a request to the queue, wait for callbacks to finish. |
+ offline_pages::SavePageRequest request( |
+ kRequestId, kUrl, kClientId, base::Time::Now()); |
+ coordinator()->queue()->AddRequest( |
+ request, |
+ base::Bind(&RequestCoordinatorTest::AddRequestDone, |
+ base::Unretained(this))); |
+ PumpLoop(); |
+ |
+ // Ensure the start processing request stops before the completion callback. |
+ SkipOfflinerCallback(); |
+ |
+ DeviceConditions device_conditions(false, 75, |
+ net::NetworkChangeNotifier::CONNECTION_3G); |
+ base::Callback<void(bool)> callback = |
+ base::Bind( |
+ &RequestCoordinatorTest::EmptyCallbackFunction, |
+ base::Unretained(this)); |
+ EXPECT_TRUE(coordinator()->StartProcessing(device_conditions, callback)); |
+ |
+ // Let all the async parts of the start processing pipeline run to completion. |
+ PumpLoop(); |
+ |
+ // Now we cancel it while the prerenderer is busy. |
+ coordinator()->StopProcessing(); |
+ |
+ // Let the async callbacks in the cancel run. |
+ PumpLoop(); |
+ |
+ // OfflinerDoneCallback will not end up getting called with status SAVED, |
+ // Since we cancelled the event before it called offliner_->LoadAndSave(). |
+ EXPECT_EQ(Offliner::RequestStatus::CANCELED, last_offlining_status()); |
+} |
+ |
} // namespace offline_pages |