Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / components / dom_distiller / core / task_tracker_unittest.cc
blobd673553fb2eb820215458ce07bff93e6a79f01e0
1 // Copyright 2013 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.
5 #include "components/dom_distiller/core/task_tracker.h"
7 #include "base/run_loop.h"
8 #include "components/dom_distiller/core/article_distillation_update.h"
9 #include "components/dom_distiller/core/article_entry.h"
10 #include "components/dom_distiller/core/distilled_content_store.h"
11 #include "components/dom_distiller/core/fake_distiller.h"
12 #include "testing/gtest/include/gtest/gtest.h"
14 using testing::Return;
15 using testing::_;
17 namespace dom_distiller {
18 namespace test {
20 class FakeViewRequestDelegate : public ViewRequestDelegate {
21 public:
22 virtual ~FakeViewRequestDelegate() {}
23 MOCK_METHOD1(OnArticleReady,
24 void(const DistilledArticleProto* article_proto));
25 MOCK_METHOD1(OnArticleUpdated,
26 void(ArticleDistillationUpdate article_update));
29 class MockContentStore : public DistilledContentStore {
30 public:
31 MOCK_METHOD2(LoadContent,
32 void(const ArticleEntry& entry, LoadCallback callback));
33 MOCK_METHOD3(SaveContent,
34 void(const ArticleEntry& entry,
35 const DistilledArticleProto& proto,
36 SaveCallback callback));
39 class TestCancelCallback {
40 public:
41 TestCancelCallback() : cancelled_(false) {}
42 TaskTracker::CancelCallback GetCallback() {
43 return base::Bind(&TestCancelCallback::Cancel, base::Unretained(this));
45 void Cancel(TaskTracker*) { cancelled_ = true; }
46 bool Cancelled() { return cancelled_; }
48 private:
49 bool cancelled_;
52 class MockSaveCallback {
53 public:
54 MOCK_METHOD3(Save,
55 void(const ArticleEntry&, const DistilledArticleProto*, bool));
58 class DomDistillerTaskTrackerTest : public testing::Test {
59 public:
60 void SetUp() override {
61 message_loop_.reset(new base::MessageLoop());
62 entry_id_ = "id0";
63 page_0_url_ = GURL("http://www.example.com/1");
64 page_1_url_ = GURL("http://www.example.com/2");
67 ArticleEntry GetDefaultEntry() {
68 ArticleEntry entry;
69 entry.set_entry_id(entry_id_);
70 ArticleEntryPage* page0 = entry.add_pages();
71 ArticleEntryPage* page1 = entry.add_pages();
72 page0->set_url(page_0_url_.spec());
73 page1->set_url(page_1_url_.spec());
74 return entry;
77 protected:
78 scoped_ptr<base::MessageLoop> message_loop_;
79 std::string entry_id_;
80 GURL page_0_url_;
81 GURL page_1_url_;
84 TEST_F(DomDistillerTaskTrackerTest, TestHasEntryId) {
85 MockDistillerFactory distiller_factory;
86 TestCancelCallback cancel_callback;
87 TaskTracker task_tracker(
88 GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
89 EXPECT_TRUE(task_tracker.HasEntryId(entry_id_));
90 EXPECT_FALSE(task_tracker.HasEntryId("other_id"));
93 TEST_F(DomDistillerTaskTrackerTest, TestHasUrl) {
94 MockDistillerFactory distiller_factory;
95 TestCancelCallback cancel_callback;
96 TaskTracker task_tracker(
97 GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
98 EXPECT_TRUE(task_tracker.HasUrl(page_0_url_));
99 EXPECT_TRUE(task_tracker.HasUrl(page_1_url_));
100 EXPECT_FALSE(task_tracker.HasUrl(GURL("http://other.url/")));
103 TEST_F(DomDistillerTaskTrackerTest, TestViewerCancelled) {
104 MockDistillerFactory distiller_factory;
105 TestCancelCallback cancel_callback;
106 TaskTracker task_tracker(
107 GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
109 FakeViewRequestDelegate viewer_delegate;
110 FakeViewRequestDelegate viewer_delegate2;
111 scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
112 scoped_ptr<ViewerHandle> handle2(task_tracker.AddViewer(&viewer_delegate2));
114 EXPECT_FALSE(cancel_callback.Cancelled());
115 handle.reset();
116 EXPECT_FALSE(cancel_callback.Cancelled());
117 handle2.reset();
118 EXPECT_TRUE(cancel_callback.Cancelled());
121 TEST_F(DomDistillerTaskTrackerTest, TestViewerCancelledWithSaveRequest) {
122 MockDistillerFactory distiller_factory;
123 TestCancelCallback cancel_callback;
124 TaskTracker task_tracker(
125 GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
127 FakeViewRequestDelegate viewer_delegate;
128 scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
129 EXPECT_FALSE(cancel_callback.Cancelled());
131 MockSaveCallback save_callback;
132 task_tracker.AddSaveCallback(
133 base::Bind(&MockSaveCallback::Save, base::Unretained(&save_callback)));
134 handle.reset();
136 // Since there is a pending save request, the task shouldn't be cancelled.
137 EXPECT_FALSE(cancel_callback.Cancelled());
140 TEST_F(DomDistillerTaskTrackerTest, TestViewerNotifiedOnDistillationComplete) {
141 MockDistillerFactory distiller_factory;
142 FakeDistiller* distiller = new FakeDistiller(true);
143 EXPECT_CALL(distiller_factory, CreateDistillerImpl())
144 .WillOnce(Return(distiller));
145 TestCancelCallback cancel_callback;
146 TaskTracker task_tracker(
147 GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
149 FakeViewRequestDelegate viewer_delegate;
150 scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
151 base::RunLoop().RunUntilIdle();
153 EXPECT_CALL(viewer_delegate, OnArticleReady(_));
155 task_tracker.StartDistiller(&distiller_factory,
156 scoped_ptr<DistillerPage>().Pass());
157 base::RunLoop().RunUntilIdle();
159 EXPECT_FALSE(cancel_callback.Cancelled());
162 TEST_F(DomDistillerTaskTrackerTest, TestDistillerFails) {
163 MockDistillerFactory distiller_factory;
164 FakeDistiller* distiller = new FakeDistiller(false);
165 EXPECT_CALL(distiller_factory, CreateDistillerImpl())
166 .WillOnce(Return(distiller));
168 TestCancelCallback cancel_callback;
169 TaskTracker task_tracker(
170 GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
172 FakeViewRequestDelegate viewer_delegate;
173 scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
174 base::RunLoop().RunUntilIdle();
176 EXPECT_CALL(viewer_delegate, OnArticleReady(_));
178 task_tracker.StartDistiller(&distiller_factory,
179 scoped_ptr<DistillerPage>().Pass());
180 distiller->RunDistillerCallback(
181 scoped_ptr<DistilledArticleProto>(new DistilledArticleProto));
182 base::RunLoop().RunUntilIdle();
184 EXPECT_FALSE(cancel_callback.Cancelled());
187 TEST_F(DomDistillerTaskTrackerTest,
188 TestSaveCallbackCalledOnDistillationComplete) {
189 MockDistillerFactory distiller_factory;
190 FakeDistiller* distiller = new FakeDistiller(true);
191 EXPECT_CALL(distiller_factory, CreateDistillerImpl())
192 .WillOnce(Return(distiller));
193 TestCancelCallback cancel_callback;
194 TaskTracker task_tracker(
195 GetDefaultEntry(), cancel_callback.GetCallback(), NULL);
197 MockSaveCallback save_callback;
198 task_tracker.AddSaveCallback(
199 base::Bind(&MockSaveCallback::Save, base::Unretained(&save_callback)));
200 base::RunLoop().RunUntilIdle();
202 EXPECT_CALL(save_callback, Save(_, _, _));
204 task_tracker.StartDistiller(&distiller_factory,
205 scoped_ptr<DistillerPage>().Pass());
206 base::RunLoop().RunUntilIdle();
208 EXPECT_TRUE(cancel_callback.Cancelled());
211 DistilledArticleProto CreateDistilledArticleForEntry(
212 const ArticleEntry& entry) {
213 DistilledArticleProto article;
214 for (int i = 0; i < entry.pages_size(); ++i) {
215 DistilledPageProto* page = article.add_pages();
216 page->set_url(entry.pages(i).url());
217 page->set_html("<div>" + entry.pages(i).url() + "</div>");
219 return article;
222 TEST_F(DomDistillerTaskTrackerTest, TestBlobFetcher) {
223 ArticleEntry entry_with_blob = GetDefaultEntry();
224 DistilledArticleProto stored_distilled_article =
225 CreateDistilledArticleForEntry(entry_with_blob);
226 InMemoryContentStore content_store(kDefaultMaxNumCachedEntries);
227 content_store.InjectContent(entry_with_blob, stored_distilled_article);
228 TestCancelCallback cancel_callback;
230 TaskTracker task_tracker(
231 entry_with_blob, cancel_callback.GetCallback(), &content_store);
233 FakeViewRequestDelegate viewer_delegate;
234 scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
235 base::RunLoop().RunUntilIdle();
237 const DistilledArticleProto* distilled_article;
239 EXPECT_CALL(viewer_delegate, OnArticleReady(_))
240 .WillOnce(testing::SaveArg<0>(&distilled_article));
242 task_tracker.StartBlobFetcher();
243 base::RunLoop().RunUntilIdle();
245 EXPECT_EQ(stored_distilled_article.SerializeAsString(),
246 distilled_article->SerializeAsString());
248 EXPECT_FALSE(cancel_callback.Cancelled());
251 TEST_F(DomDistillerTaskTrackerTest, TestBlobFetcherFinishesFirst) {
252 MockDistillerFactory distiller_factory;
253 FakeDistiller* distiller = new FakeDistiller(false);
254 EXPECT_CALL(distiller_factory, CreateDistillerImpl())
255 .WillOnce(Return(distiller));
257 ArticleEntry entry_with_blob = GetDefaultEntry();
258 DistilledArticleProto stored_distilled_article =
259 CreateDistilledArticleForEntry(entry_with_blob);
260 InMemoryContentStore content_store(kDefaultMaxNumCachedEntries);
261 content_store.InjectContent(entry_with_blob, stored_distilled_article);
262 TestCancelCallback cancel_callback;
263 TaskTracker task_tracker(
264 entry_with_blob, cancel_callback.GetCallback(), &content_store);
266 FakeViewRequestDelegate viewer_delegate;
267 scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
268 base::RunLoop().RunUntilIdle();
270 DistilledArticleProto distilled_article;
272 EXPECT_CALL(viewer_delegate, OnArticleReady(_))
273 .WillOnce(testing::SaveArgPointee<0>(&distilled_article));
274 bool distiller_destroyed = false;
275 EXPECT_CALL(*distiller, Die())
276 .WillOnce(testing::Assign(&distiller_destroyed, true));
278 task_tracker.StartDistiller(&distiller_factory,
279 scoped_ptr<DistillerPage>().Pass());
280 task_tracker.StartBlobFetcher();
281 base::RunLoop().RunUntilIdle();
283 testing::Mock::VerifyAndClearExpectations(&viewer_delegate);
284 EXPECT_EQ(stored_distilled_article.SerializeAsString(),
285 distilled_article.SerializeAsString());
287 EXPECT_TRUE(distiller_destroyed);
288 EXPECT_FALSE(cancel_callback.Cancelled());
289 base::RunLoop().RunUntilIdle();
292 TEST_F(DomDistillerTaskTrackerTest, TestBlobFetcherWithoutBlob) {
293 MockDistillerFactory distiller_factory;
294 FakeDistiller* distiller = new FakeDistiller(false);
295 EXPECT_CALL(distiller_factory, CreateDistillerImpl())
296 .WillOnce(Return(distiller));
298 ArticleEntry entry(GetDefaultEntry());
299 InMemoryContentStore content_store(kDefaultMaxNumCachedEntries);
300 scoped_ptr<DistilledArticleProto> distilled_article(
301 new DistilledArticleProto(CreateDistilledArticleForEntry(entry)));
303 TestCancelCallback cancel_callback;
304 TaskTracker task_tracker(
305 GetDefaultEntry(), cancel_callback.GetCallback(), &content_store);
307 FakeViewRequestDelegate viewer_delegate;
308 scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
309 base::RunLoop().RunUntilIdle();
311 task_tracker.StartBlobFetcher();
312 task_tracker.StartDistiller(&distiller_factory,
313 scoped_ptr<DistillerPage>().Pass());
315 // OnArticleReady shouldn't be called until distillation finishes (i.e. the
316 // blob fetcher shouldn't return distilled content).
317 EXPECT_CALL(viewer_delegate, OnArticleReady(_)).Times(0);
318 base::RunLoop().RunUntilIdle();
320 EXPECT_CALL(viewer_delegate, OnArticleReady(_));
321 distiller->RunDistillerCallback(distilled_article.Pass());
322 base::RunLoop().RunUntilIdle();
324 EXPECT_FALSE(cancel_callback.Cancelled());
327 TEST_F(DomDistillerTaskTrackerTest, TestDistillerFailsFirst) {
328 MockDistillerFactory distiller_factory;
329 FakeDistiller* distiller = new FakeDistiller(false);
330 EXPECT_CALL(distiller_factory, CreateDistillerImpl())
331 .WillOnce(Return(distiller));
333 ArticleEntry entry(GetDefaultEntry());
334 MockContentStore content_store;
336 TestCancelCallback cancel_callback;
337 TaskTracker task_tracker(
338 GetDefaultEntry(), cancel_callback.GetCallback(), &content_store);
340 FakeViewRequestDelegate viewer_delegate;
341 scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
343 DistilledContentStore::LoadCallback content_store_load_callback;
344 EXPECT_CALL(content_store, LoadContent(_, _))
345 .WillOnce(testing::SaveArg<1>(&content_store_load_callback));
347 task_tracker.StartDistiller(&distiller_factory,
348 scoped_ptr<DistillerPage>().Pass());
349 task_tracker.StartBlobFetcher();
351 EXPECT_CALL(viewer_delegate, OnArticleReady(_)).Times(0);
352 distiller->RunDistillerCallback(
353 scoped_ptr<DistilledArticleProto>(new DistilledArticleProto));
354 base::RunLoop().RunUntilIdle();
356 EXPECT_CALL(viewer_delegate, OnArticleReady(_));
357 content_store_load_callback.Run(
358 true,
359 scoped_ptr<DistilledArticleProto>(
360 new DistilledArticleProto(CreateDistilledArticleForEntry(entry))));
361 base::RunLoop().RunUntilIdle();
363 EXPECT_FALSE(cancel_callback.Cancelled());
366 TEST_F(DomDistillerTaskTrackerTest, ContentIsSaved) {
367 MockDistillerFactory distiller_factory;
368 FakeDistiller* distiller = new FakeDistiller(false);
369 EXPECT_CALL(distiller_factory, CreateDistillerImpl())
370 .WillOnce(Return(distiller));
372 ArticleEntry entry(GetDefaultEntry());
373 DistilledArticleProto distilled_article =
374 CreateDistilledArticleForEntry(entry);
376 MockContentStore content_store;
377 TestCancelCallback cancel_callback;
378 TaskTracker task_tracker(
379 GetDefaultEntry(), cancel_callback.GetCallback(), &content_store);
381 FakeViewRequestDelegate viewer_delegate;
382 scoped_ptr<ViewerHandle> handle(task_tracker.AddViewer(&viewer_delegate));
384 DistilledArticleProto stored_distilled_article;
385 DistilledContentStore::LoadCallback content_store_load_callback;
386 EXPECT_CALL(content_store, SaveContent(_, _, _))
387 .WillOnce(testing::SaveArg<1>(&stored_distilled_article));
389 task_tracker.StartDistiller(&distiller_factory,
390 scoped_ptr<DistillerPage>().Pass());
392 EXPECT_CALL(viewer_delegate, OnArticleReady(_));
393 distiller->RunDistillerCallback(scoped_ptr<DistilledArticleProto>(
394 new DistilledArticleProto(distilled_article)));
395 base::RunLoop().RunUntilIdle();
397 ASSERT_EQ(stored_distilled_article.SerializeAsString(),
398 distilled_article.SerializeAsString());
399 EXPECT_FALSE(cancel_callback.Cancelled());
402 } // namespace test
403 } // namespace dom_distiller