task_tracker_unittest.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416
  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.
  4. #include "components/dom_distiller/core/task_tracker.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/run_loop.h"
  9. #include "base/test/gmock_move_support.h"
  10. #include "base/test/task_environment.h"
  11. #include "components/dom_distiller/core/article_distillation_update.h"
  12. #include "components/dom_distiller/core/article_entry.h"
  13. #include "components/dom_distiller/core/distilled_content_store.h"
  14. #include "components/dom_distiller/core/fake_distiller.h"
  15. #include "testing/gtest/include/gtest/gtest.h"
  16. using testing::_;
  17. using testing::Return;
  18. namespace dom_distiller {
  19. namespace test {
  20. class FakeViewRequestDelegate : public ViewRequestDelegate {
  21. public:
  22. ~FakeViewRequestDelegate() override = default;
  23. MOCK_METHOD1(OnArticleReady,
  24. void(const DistilledArticleProto* article_proto));
  25. MOCK_METHOD1(OnArticleUpdated,
  26. void(ArticleDistillationUpdate article_update));
  27. };
  28. class MockContentStore : public DistilledContentStore {
  29. public:
  30. void LoadContent(const ArticleEntry& entry, LoadCallback callback) override {
  31. LoadContent_(entry, callback);
  32. }
  33. MOCK_METHOD2(LoadContent_,
  34. void(const ArticleEntry& entry, LoadCallback& callback));
  35. MOCK_METHOD3(SaveContent,
  36. void(const ArticleEntry& entry,
  37. const DistilledArticleProto& proto,
  38. SaveCallback callback));
  39. };
  40. class TestCancelCallback {
  41. public:
  42. TestCancelCallback() : cancelled_(false) {}
  43. TaskTracker::CancelCallback GetCallback() {
  44. return base::BindOnce(&TestCancelCallback::Cancel, base::Unretained(this));
  45. }
  46. void Cancel(TaskTracker*) { cancelled_ = true; }
  47. bool Cancelled() { return cancelled_; }
  48. private:
  49. bool cancelled_;
  50. };
  51. class MockSaveCallback {
  52. public:
  53. MOCK_METHOD3(Save,
  54. void(const ArticleEntry&, const DistilledArticleProto*, bool));
  55. };
  56. class DomDistillerTaskTrackerTest : public testing::Test {
  57. public:
  58. void SetUp() override {
  59. entry_id_ = "id0";
  60. page_0_url_ = GURL("http://www.example.com/1");
  61. page_1_url_ = GURL("http://www.example.com/2");
  62. }
  63. ArticleEntry GetDefaultEntry() {
  64. ArticleEntry entry;
  65. entry.entry_id = entry_id_;
  66. entry.pages.push_back(page_0_url_);
  67. entry.pages.push_back(page_1_url_);
  68. return entry;
  69. }
  70. protected:
  71. base::test::SingleThreadTaskEnvironment task_environment_;
  72. std::string entry_id_;
  73. GURL page_0_url_;
  74. GURL page_1_url_;
  75. };
  76. TEST_F(DomDistillerTaskTrackerTest, TestHasEntryId) {
  77. MockDistillerFactory distiller_factory;
  78. TestCancelCallback cancel_callback;
  79. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  80. nullptr);
  81. EXPECT_TRUE(task_tracker.HasEntryId(entry_id_));
  82. EXPECT_FALSE(task_tracker.HasEntryId("other_id"));
  83. }
  84. TEST_F(DomDistillerTaskTrackerTest, TestHasUrl) {
  85. MockDistillerFactory distiller_factory;
  86. TestCancelCallback cancel_callback;
  87. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  88. nullptr);
  89. EXPECT_TRUE(task_tracker.HasUrl(page_0_url_));
  90. EXPECT_TRUE(task_tracker.HasUrl(page_1_url_));
  91. EXPECT_FALSE(task_tracker.HasUrl(GURL("http://other.url/")));
  92. }
  93. TEST_F(DomDistillerTaskTrackerTest, TestViewerCancelled) {
  94. MockDistillerFactory distiller_factory;
  95. TestCancelCallback cancel_callback;
  96. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  97. nullptr);
  98. FakeViewRequestDelegate viewer_delegate;
  99. FakeViewRequestDelegate viewer_delegate2;
  100. std::unique_ptr<ViewerHandle> handle(
  101. task_tracker.AddViewer(&viewer_delegate));
  102. std::unique_ptr<ViewerHandle> handle2(
  103. task_tracker.AddViewer(&viewer_delegate2));
  104. EXPECT_FALSE(cancel_callback.Cancelled());
  105. handle.reset();
  106. EXPECT_FALSE(cancel_callback.Cancelled());
  107. handle2.reset();
  108. EXPECT_TRUE(cancel_callback.Cancelled());
  109. }
  110. TEST_F(DomDistillerTaskTrackerTest, TestViewerCancelledWithSaveRequest) {
  111. MockDistillerFactory distiller_factory;
  112. TestCancelCallback cancel_callback;
  113. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  114. nullptr);
  115. FakeViewRequestDelegate viewer_delegate;
  116. std::unique_ptr<ViewerHandle> handle(
  117. task_tracker.AddViewer(&viewer_delegate));
  118. EXPECT_FALSE(cancel_callback.Cancelled());
  119. MockSaveCallback save_callback;
  120. task_tracker.AddSaveCallback(base::BindOnce(
  121. &MockSaveCallback::Save, base::Unretained(&save_callback)));
  122. handle.reset();
  123. // Since there is a pending save request, the task shouldn't be cancelled.
  124. EXPECT_FALSE(cancel_callback.Cancelled());
  125. }
  126. TEST_F(DomDistillerTaskTrackerTest, TestViewerNotifiedOnDistillationComplete) {
  127. MockDistillerFactory distiller_factory;
  128. FakeDistiller* distiller = new FakeDistiller(true);
  129. EXPECT_CALL(distiller_factory, CreateDistillerImpl())
  130. .WillOnce(Return(distiller));
  131. TestCancelCallback cancel_callback;
  132. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  133. nullptr);
  134. FakeViewRequestDelegate viewer_delegate;
  135. std::unique_ptr<ViewerHandle> handle(
  136. task_tracker.AddViewer(&viewer_delegate));
  137. base::RunLoop().RunUntilIdle();
  138. EXPECT_CALL(viewer_delegate, OnArticleReady(_));
  139. task_tracker.StartDistiller(&distiller_factory,
  140. std::unique_ptr<DistillerPage>());
  141. base::RunLoop().RunUntilIdle();
  142. EXPECT_FALSE(cancel_callback.Cancelled());
  143. }
  144. TEST_F(DomDistillerTaskTrackerTest, TestDistillerFails) {
  145. MockDistillerFactory distiller_factory;
  146. FakeDistiller* distiller = new FakeDistiller(false);
  147. EXPECT_CALL(distiller_factory, CreateDistillerImpl())
  148. .WillOnce(Return(distiller));
  149. TestCancelCallback cancel_callback;
  150. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  151. nullptr);
  152. FakeViewRequestDelegate viewer_delegate;
  153. std::unique_ptr<ViewerHandle> handle(
  154. task_tracker.AddViewer(&viewer_delegate));
  155. base::RunLoop().RunUntilIdle();
  156. EXPECT_CALL(viewer_delegate, OnArticleReady(_));
  157. task_tracker.StartDistiller(&distiller_factory,
  158. std::unique_ptr<DistillerPage>());
  159. distiller->RunDistillerCallback(std::make_unique<DistilledArticleProto>());
  160. base::RunLoop().RunUntilIdle();
  161. EXPECT_FALSE(cancel_callback.Cancelled());
  162. }
  163. TEST_F(DomDistillerTaskTrackerTest,
  164. TestSaveCallbackCalledOnDistillationComplete) {
  165. MockDistillerFactory distiller_factory;
  166. FakeDistiller* distiller = new FakeDistiller(true);
  167. EXPECT_CALL(distiller_factory, CreateDistillerImpl())
  168. .WillOnce(Return(distiller));
  169. TestCancelCallback cancel_callback;
  170. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  171. nullptr);
  172. MockSaveCallback save_callback;
  173. task_tracker.AddSaveCallback(base::BindOnce(
  174. &MockSaveCallback::Save, base::Unretained(&save_callback)));
  175. base::RunLoop().RunUntilIdle();
  176. EXPECT_CALL(save_callback, Save(_, _, _));
  177. task_tracker.StartDistiller(&distiller_factory,
  178. std::unique_ptr<DistillerPage>());
  179. base::RunLoop().RunUntilIdle();
  180. EXPECT_TRUE(cancel_callback.Cancelled());
  181. }
  182. DistilledArticleProto CreateDistilledArticleForEntry(
  183. const ArticleEntry& entry) {
  184. DistilledArticleProto article;
  185. for (const GURL& url : entry.pages) {
  186. DistilledPageProto* page = article.add_pages();
  187. page->set_url(url.spec());
  188. page->set_html("<div>" + url.spec() + "</div>");
  189. }
  190. return article;
  191. }
  192. TEST_F(DomDistillerTaskTrackerTest, TestBlobFetcher) {
  193. ArticleEntry entry_with_blob = GetDefaultEntry();
  194. DistilledArticleProto stored_distilled_article =
  195. CreateDistilledArticleForEntry(entry_with_blob);
  196. InMemoryContentStore content_store(kDefaultMaxNumCachedEntries);
  197. content_store.InjectContent(entry_with_blob, stored_distilled_article);
  198. TestCancelCallback cancel_callback;
  199. TaskTracker task_tracker(entry_with_blob, cancel_callback.GetCallback(),
  200. &content_store);
  201. FakeViewRequestDelegate viewer_delegate;
  202. std::unique_ptr<ViewerHandle> handle(
  203. task_tracker.AddViewer(&viewer_delegate));
  204. base::RunLoop().RunUntilIdle();
  205. const DistilledArticleProto* distilled_article;
  206. EXPECT_CALL(viewer_delegate, OnArticleReady(_))
  207. .WillOnce(testing::SaveArg<0>(&distilled_article));
  208. task_tracker.StartBlobFetcher();
  209. base::RunLoop().RunUntilIdle();
  210. EXPECT_EQ(stored_distilled_article.SerializeAsString(),
  211. distilled_article->SerializeAsString());
  212. EXPECT_FALSE(cancel_callback.Cancelled());
  213. }
  214. TEST_F(DomDistillerTaskTrackerTest, TestBlobFetcherFinishesFirst) {
  215. MockDistillerFactory distiller_factory;
  216. FakeDistiller* distiller = new FakeDistiller(false);
  217. EXPECT_CALL(distiller_factory, CreateDistillerImpl())
  218. .WillOnce(Return(distiller));
  219. ArticleEntry entry_with_blob = GetDefaultEntry();
  220. DistilledArticleProto stored_distilled_article =
  221. CreateDistilledArticleForEntry(entry_with_blob);
  222. InMemoryContentStore content_store(kDefaultMaxNumCachedEntries);
  223. content_store.InjectContent(entry_with_blob, stored_distilled_article);
  224. TestCancelCallback cancel_callback;
  225. TaskTracker task_tracker(entry_with_blob, cancel_callback.GetCallback(),
  226. &content_store);
  227. FakeViewRequestDelegate viewer_delegate;
  228. std::unique_ptr<ViewerHandle> handle(
  229. task_tracker.AddViewer(&viewer_delegate));
  230. base::RunLoop().RunUntilIdle();
  231. DistilledArticleProto distilled_article;
  232. EXPECT_CALL(viewer_delegate, OnArticleReady(_))
  233. .WillOnce(testing::SaveArgPointee<0>(&distilled_article));
  234. bool distiller_destroyed = false;
  235. EXPECT_CALL(*distiller, Die())
  236. .WillOnce(testing::Assign(&distiller_destroyed, true));
  237. task_tracker.StartDistiller(&distiller_factory,
  238. std::unique_ptr<DistillerPage>());
  239. task_tracker.StartBlobFetcher();
  240. base::RunLoop().RunUntilIdle();
  241. testing::Mock::VerifyAndClearExpectations(&viewer_delegate);
  242. EXPECT_EQ(stored_distilled_article.SerializeAsString(),
  243. distilled_article.SerializeAsString());
  244. EXPECT_TRUE(distiller_destroyed);
  245. EXPECT_FALSE(cancel_callback.Cancelled());
  246. base::RunLoop().RunUntilIdle();
  247. }
  248. TEST_F(DomDistillerTaskTrackerTest, TestBlobFetcherWithoutBlob) {
  249. MockDistillerFactory distiller_factory;
  250. FakeDistiller* distiller = new FakeDistiller(false);
  251. EXPECT_CALL(distiller_factory, CreateDistillerImpl())
  252. .WillOnce(Return(distiller));
  253. ArticleEntry entry(GetDefaultEntry());
  254. InMemoryContentStore content_store(kDefaultMaxNumCachedEntries);
  255. std::unique_ptr<DistilledArticleProto> distilled_article(
  256. new DistilledArticleProto(CreateDistilledArticleForEntry(entry)));
  257. TestCancelCallback cancel_callback;
  258. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  259. &content_store);
  260. FakeViewRequestDelegate viewer_delegate;
  261. std::unique_ptr<ViewerHandle> handle(
  262. task_tracker.AddViewer(&viewer_delegate));
  263. base::RunLoop().RunUntilIdle();
  264. task_tracker.StartBlobFetcher();
  265. task_tracker.StartDistiller(&distiller_factory,
  266. std::unique_ptr<DistillerPage>());
  267. // OnArticleReady shouldn't be called until distillation finishes (i.e. the
  268. // blob fetcher shouldn't return distilled content).
  269. EXPECT_CALL(viewer_delegate, OnArticleReady(_)).Times(0);
  270. base::RunLoop().RunUntilIdle();
  271. EXPECT_CALL(viewer_delegate, OnArticleReady(_));
  272. distiller->RunDistillerCallback(std::move(distilled_article));
  273. base::RunLoop().RunUntilIdle();
  274. EXPECT_FALSE(cancel_callback.Cancelled());
  275. }
  276. TEST_F(DomDistillerTaskTrackerTest, TestDistillerFailsFirst) {
  277. MockDistillerFactory distiller_factory;
  278. FakeDistiller* distiller = new FakeDistiller(false);
  279. EXPECT_CALL(distiller_factory, CreateDistillerImpl())
  280. .WillOnce(Return(distiller));
  281. ArticleEntry entry(GetDefaultEntry());
  282. MockContentStore content_store;
  283. TestCancelCallback cancel_callback;
  284. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  285. &content_store);
  286. FakeViewRequestDelegate viewer_delegate;
  287. std::unique_ptr<ViewerHandle> handle(
  288. task_tracker.AddViewer(&viewer_delegate));
  289. DistilledContentStore::LoadCallback content_store_load_callback;
  290. EXPECT_CALL(content_store, LoadContent_(_, _))
  291. .WillOnce(MoveArg<1>(&content_store_load_callback));
  292. task_tracker.StartDistiller(&distiller_factory,
  293. std::unique_ptr<DistillerPage>());
  294. task_tracker.StartBlobFetcher();
  295. EXPECT_CALL(viewer_delegate, OnArticleReady(_)).Times(0);
  296. distiller->RunDistillerCallback(std::make_unique<DistilledArticleProto>());
  297. base::RunLoop().RunUntilIdle();
  298. EXPECT_CALL(viewer_delegate, OnArticleReady(_));
  299. std::move(content_store_load_callback)
  300. .Run(true, std::make_unique<DistilledArticleProto>(
  301. CreateDistilledArticleForEntry(entry)));
  302. base::RunLoop().RunUntilIdle();
  303. EXPECT_FALSE(cancel_callback.Cancelled());
  304. }
  305. TEST_F(DomDistillerTaskTrackerTest, ContentIsSaved) {
  306. MockDistillerFactory distiller_factory;
  307. FakeDistiller* distiller = new FakeDistiller(false);
  308. EXPECT_CALL(distiller_factory, CreateDistillerImpl())
  309. .WillOnce(Return(distiller));
  310. ArticleEntry entry(GetDefaultEntry());
  311. DistilledArticleProto distilled_article =
  312. CreateDistilledArticleForEntry(entry);
  313. MockContentStore content_store;
  314. TestCancelCallback cancel_callback;
  315. TaskTracker task_tracker(GetDefaultEntry(), cancel_callback.GetCallback(),
  316. &content_store);
  317. FakeViewRequestDelegate viewer_delegate;
  318. std::unique_ptr<ViewerHandle> handle(
  319. task_tracker.AddViewer(&viewer_delegate));
  320. DistilledArticleProto stored_distilled_article;
  321. DistilledContentStore::LoadCallback content_store_load_callback;
  322. EXPECT_CALL(content_store, SaveContent(_, _, _))
  323. .WillOnce(testing::SaveArg<1>(&stored_distilled_article));
  324. task_tracker.StartDistiller(&distiller_factory,
  325. std::unique_ptr<DistillerPage>());
  326. EXPECT_CALL(viewer_delegate, OnArticleReady(_));
  327. distiller->RunDistillerCallback(
  328. std::make_unique<DistilledArticleProto>(distilled_article));
  329. base::RunLoop().RunUntilIdle();
  330. ASSERT_EQ(stored_distilled_article.SerializeAsString(),
  331. distilled_article.SerializeAsString());
  332. EXPECT_FALSE(cancel_callback.Cancelled());
  333. }
  334. } // namespace test
  335. } // namespace dom_distiller