Make sure webrtc::VideoSource is released when WebRtcVideoTrackAdapter is destroyed.
[chromium-blink-merge.git] / components / dom_distiller / core / dom_distiller_service_unittest.cc
blobabb803162571fa4cd425181a2245939fb49ba691
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/dom_distiller_service.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/containers/hash_tables.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/run_loop.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "components/dom_distiller/core/article_entry.h"
14 #include "components/dom_distiller/core/dom_distiller_model.h"
15 #include "components/dom_distiller/core/dom_distiller_store.h"
16 #include "components/dom_distiller/core/dom_distiller_test_util.h"
17 #include "components/dom_distiller/core/fake_db.h"
18 #include "components/dom_distiller/core/fake_distiller.h"
19 #include "components/dom_distiller/core/fake_distiller_page.h"
20 #include "components/dom_distiller/core/task_tracker.h"
21 #include "testing/gmock/include/gmock/gmock.h"
22 #include "testing/gtest/include/gtest/gtest.h"
24 using testing::Invoke;
25 using testing::Return;
26 using testing::_;
28 namespace dom_distiller {
29 namespace test {
31 namespace {
33 class FakeViewRequestDelegate : public ViewRequestDelegate {
34 public:
35 virtual ~FakeViewRequestDelegate() {}
36 MOCK_METHOD1(OnArticleReady, void(const DistilledArticleProto* proto));
37 MOCK_METHOD1(OnArticleUpdated,
38 void(ArticleDistillationUpdate article_update));
41 class MockDistillerObserver : public DomDistillerObserver {
42 public:
43 MOCK_METHOD1(ArticleEntriesUpdated, void(const std::vector<ArticleUpdate>&));
44 virtual ~MockDistillerObserver() {}
47 class MockArticleAvailableCallback {
48 public:
49 MOCK_METHOD1(DistillationCompleted, void(bool));
52 DomDistillerService::ArticleAvailableCallback ArticleCallback(
53 MockArticleAvailableCallback* callback) {
54 return base::Bind(&MockArticleAvailableCallback::DistillationCompleted,
55 base::Unretained(callback));
58 void RunDistillerCallback(FakeDistiller* distiller,
59 scoped_ptr<DistilledArticleProto> proto) {
60 distiller->RunDistillerCallback(proto.Pass());
61 base::RunLoop().RunUntilIdle();
64 scoped_ptr<DistilledArticleProto> CreateArticleWithURL(const std::string& url) {
65 scoped_ptr<DistilledArticleProto> proto(new DistilledArticleProto);
66 DistilledPageProto* page = proto->add_pages();
67 page->set_url(url);
68 return proto.Pass();
71 scoped_ptr<DistilledArticleProto> CreateDefaultArticle() {
72 return CreateArticleWithURL("http://www.example.com/default_article_page1")
73 .Pass();
76 } // namespace
78 class DomDistillerServiceTest : public testing::Test {
79 public:
80 virtual void SetUp() {
81 main_loop_.reset(new base::MessageLoop());
82 FakeDB* fake_db = new FakeDB(&db_model_);
83 FakeDB::EntryMap store_model;
84 store_ = test::util::CreateStoreWithFakeDB(fake_db, store_model);
85 distiller_factory_ = new MockDistillerFactory();
86 distiller_page_factory_ = new MockDistillerPageFactory();
87 service_.reset(new DomDistillerService(
88 scoped_ptr<DomDistillerStoreInterface>(store_),
89 scoped_ptr<DistillerFactory>(distiller_factory_),
90 scoped_ptr<DistillerPageFactory>(distiller_page_factory_)));
91 fake_db->InitCallback(true);
92 fake_db->LoadCallback(true);
95 virtual void TearDown() {
96 base::RunLoop().RunUntilIdle();
97 store_ = NULL;
98 distiller_factory_ = NULL;
99 service_.reset();
102 protected:
103 // store is owned by service_.
104 DomDistillerStoreInterface* store_;
105 MockDistillerFactory* distiller_factory_;
106 MockDistillerPageFactory* distiller_page_factory_;
107 scoped_ptr<DomDistillerService> service_;
108 scoped_ptr<base::MessageLoop> main_loop_;
109 FakeDB::EntryMap db_model_;
112 TEST_F(DomDistillerServiceTest, TestViewEntry) {
113 FakeDistiller* distiller = new FakeDistiller(false);
114 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
115 .WillOnce(Return(distiller));
117 GURL url("http://www.example.com/p1");
118 std::string entry_id("id0");
119 ArticleEntry entry;
120 entry.set_entry_id(entry_id);
121 entry.add_pages()->set_url(url.spec());
123 store_->AddEntry(entry);
125 FakeViewRequestDelegate viewer_delegate;
126 scoped_ptr<ViewerHandle> handle = service_->ViewEntry(
127 &viewer_delegate, service_->CreateDefaultDistillerPage(), entry_id);
129 ASSERT_FALSE(distiller->GetArticleCallback().is_null());
131 scoped_ptr<DistilledArticleProto> proto = CreateDefaultArticle();
132 EXPECT_CALL(viewer_delegate, OnArticleReady(proto.get()));
134 RunDistillerCallback(distiller, proto.Pass());
137 TEST_F(DomDistillerServiceTest, TestViewUrl) {
138 FakeDistiller* distiller = new FakeDistiller(false);
139 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
140 .WillOnce(Return(distiller));
142 FakeViewRequestDelegate viewer_delegate;
143 GURL url("http://www.example.com/p1");
144 scoped_ptr<ViewerHandle> handle = service_->ViewUrl(
145 &viewer_delegate, service_->CreateDefaultDistillerPage(), url);
147 ASSERT_FALSE(distiller->GetArticleCallback().is_null());
148 EXPECT_EQ(url, distiller->GetUrl());
150 scoped_ptr<DistilledArticleProto> proto = CreateDefaultArticle();
151 EXPECT_CALL(viewer_delegate, OnArticleReady(proto.get()));
153 RunDistillerCallback(distiller, proto.Pass());
156 TEST_F(DomDistillerServiceTest, TestMultipleViewUrl) {
157 FakeDistiller* distiller = new FakeDistiller(false);
158 FakeDistiller* distiller2 = new FakeDistiller(false);
159 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
160 .WillOnce(Return(distiller))
161 .WillOnce(Return(distiller2));
163 FakeViewRequestDelegate viewer_delegate;
164 FakeViewRequestDelegate viewer_delegate2;
166 GURL url("http://www.example.com/p1");
167 GURL url2("http://www.example.com/a/p1");
169 scoped_ptr<ViewerHandle> handle = service_->ViewUrl(
170 &viewer_delegate, service_->CreateDefaultDistillerPage(), url);
171 scoped_ptr<ViewerHandle> handle2 = service_->ViewUrl(
172 &viewer_delegate2, service_->CreateDefaultDistillerPage(), url2);
174 ASSERT_FALSE(distiller->GetArticleCallback().is_null());
175 EXPECT_EQ(url, distiller->GetUrl());
177 scoped_ptr<DistilledArticleProto> proto = CreateDefaultArticle();
178 EXPECT_CALL(viewer_delegate, OnArticleReady(proto.get()));
180 RunDistillerCallback(distiller, proto.Pass());
182 ASSERT_FALSE(distiller2->GetArticleCallback().is_null());
183 EXPECT_EQ(url2, distiller2->GetUrl());
185 scoped_ptr<DistilledArticleProto> proto2 = CreateDefaultArticle();
186 EXPECT_CALL(viewer_delegate2, OnArticleReady(proto2.get()));
188 RunDistillerCallback(distiller2, proto2.Pass());
191 TEST_F(DomDistillerServiceTest, TestViewUrlCancelled) {
192 FakeDistiller* distiller = new FakeDistiller(false);
193 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
194 .WillOnce(Return(distiller));
196 bool distiller_destroyed = false;
197 EXPECT_CALL(*distiller, Die())
198 .WillOnce(testing::Assign(&distiller_destroyed, true));
200 FakeViewRequestDelegate viewer_delegate;
201 GURL url("http://www.example.com/p1");
202 scoped_ptr<ViewerHandle> handle = service_->ViewUrl(
203 &viewer_delegate, service_->CreateDefaultDistillerPage(), url);
205 ASSERT_FALSE(distiller->GetArticleCallback().is_null());
206 EXPECT_EQ(url, distiller->GetUrl());
208 EXPECT_CALL(viewer_delegate, OnArticleReady(_)).Times(0);
210 EXPECT_FALSE(distiller_destroyed);
212 handle.reset();
213 base::RunLoop().RunUntilIdle();
214 EXPECT_TRUE(distiller_destroyed);
217 TEST_F(DomDistillerServiceTest, TestViewUrlDoesNotAddEntry) {
218 FakeDistiller* distiller = new FakeDistiller(false);
219 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
220 .WillOnce(Return(distiller));
222 FakeViewRequestDelegate viewer_delegate;
223 GURL url("http://www.example.com/p1");
224 scoped_ptr<ViewerHandle> handle = service_->ViewUrl(
225 &viewer_delegate, service_->CreateDefaultDistillerPage(), url);
227 scoped_ptr<DistilledArticleProto> proto = CreateArticleWithURL(url.spec());
228 EXPECT_CALL(viewer_delegate, OnArticleReady(proto.get()));
230 RunDistillerCallback(distiller, proto.Pass());
231 base::RunLoop().RunUntilIdle();
232 // The entry should not be added to the store.
233 EXPECT_EQ(0u, store_->GetEntries().size());
236 TEST_F(DomDistillerServiceTest, TestAddAndRemoveEntry) {
237 FakeDistiller* distiller = new FakeDistiller(false);
238 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
239 .WillOnce(Return(distiller));
241 GURL url("http://www.example.com/p1");
243 MockArticleAvailableCallback article_cb;
244 EXPECT_CALL(article_cb, DistillationCompleted(true));
246 std::string entry_id =
247 service_->AddToList(url,
248 service_->CreateDefaultDistillerPage().Pass(),
249 ArticleCallback(&article_cb));
251 ASSERT_FALSE(distiller->GetArticleCallback().is_null());
252 EXPECT_EQ(url, distiller->GetUrl());
254 scoped_ptr<DistilledArticleProto> proto = CreateArticleWithURL(url.spec());
255 RunDistillerCallback(distiller, proto.Pass());
257 ArticleEntry entry;
258 EXPECT_TRUE(store_->GetEntryByUrl(url, &entry));
259 EXPECT_EQ(entry.entry_id(), entry_id);
260 EXPECT_EQ(1u, store_->GetEntries().size());
261 service_->RemoveEntry(entry_id);
262 base::RunLoop().RunUntilIdle();
263 EXPECT_EQ(0u, store_->GetEntries().size());
266 TEST_F(DomDistillerServiceTest, TestCancellation) {
267 FakeDistiller* distiller = new FakeDistiller(false);
268 MockDistillerObserver observer;
269 service_->AddObserver(&observer);
271 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
272 .WillOnce(Return(distiller));
274 MockArticleAvailableCallback article_cb;
275 EXPECT_CALL(article_cb, DistillationCompleted(false));
277 GURL url("http://www.example.com/p1");
278 std::string entry_id =
279 service_->AddToList(url,
280 service_->CreateDefaultDistillerPage().Pass(),
281 ArticleCallback(&article_cb));
283 // Remove entry will cause the |article_cb| to be called with false value.
284 service_->RemoveEntry(entry_id);
285 base::RunLoop().RunUntilIdle();
288 TEST_F(DomDistillerServiceTest, TestMultipleObservers) {
289 FakeDistiller* distiller = new FakeDistiller(false);
290 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
291 .WillOnce(Return(distiller));
293 const int kObserverCount = 5;
294 MockDistillerObserver observers[kObserverCount];
295 for (int i = 0; i < kObserverCount; ++i) {
296 service_->AddObserver(&observers[i]);
299 DomDistillerService::ArticleAvailableCallback article_cb;
300 GURL url("http://www.example.com/p1");
301 std::string entry_id = service_->AddToList(
302 url, service_->CreateDefaultDistillerPage().Pass(), article_cb);
304 // Distillation should notify all observers that article is added.
305 std::vector<DomDistillerObserver::ArticleUpdate> expected_updates;
306 DomDistillerObserver::ArticleUpdate update;
307 update.entry_id = entry_id;
308 update.update_type = DomDistillerObserver::ArticleUpdate::ADD;
309 expected_updates.push_back(update);
311 for (int i = 0; i < kObserverCount; ++i) {
312 EXPECT_CALL(
313 observers[i],
314 ArticleEntriesUpdated(util::HasExpectedUpdates(expected_updates)));
317 scoped_ptr<DistilledArticleProto> proto = CreateDefaultArticle();
318 RunDistillerCallback(distiller, proto.Pass());
320 // Remove should notify all observers that article is removed.
321 update.update_type = DomDistillerObserver::ArticleUpdate::REMOVE;
322 expected_updates.clear();
323 expected_updates.push_back(update);
324 for (int i = 0; i < kObserverCount; ++i) {
325 EXPECT_CALL(
326 observers[i],
327 ArticleEntriesUpdated(util::HasExpectedUpdates(expected_updates)));
330 service_->RemoveEntry(entry_id);
331 base::RunLoop().RunUntilIdle();
334 TEST_F(DomDistillerServiceTest, TestMultipleCallbacks) {
335 FakeDistiller* distiller = new FakeDistiller(false);
336 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
337 .WillOnce(Return(distiller));
339 const int kClientsCount = 5;
340 MockArticleAvailableCallback article_cb[kClientsCount];
341 // Adding a URL and then distilling calls all clients.
342 GURL url("http://www.example.com/p1");
343 const std::string entry_id =
344 service_->AddToList(url,
345 service_->CreateDefaultDistillerPage().Pass(),
346 ArticleCallback(&article_cb[0]));
347 EXPECT_CALL(article_cb[0], DistillationCompleted(true));
349 for (int i = 1; i < kClientsCount; ++i) {
350 EXPECT_EQ(entry_id,
351 service_->AddToList(url,
352 service_->CreateDefaultDistillerPage().Pass(),
353 ArticleCallback(&article_cb[i])));
354 EXPECT_CALL(article_cb[i], DistillationCompleted(true));
357 scoped_ptr<DistilledArticleProto> proto = CreateArticleWithURL(url.spec());
358 RunDistillerCallback(distiller, proto.Pass());
360 // Add the same url again, all callbacks should be called with true.
361 for (int i = 0; i < kClientsCount; ++i) {
362 EXPECT_CALL(article_cb[i], DistillationCompleted(true));
363 EXPECT_EQ(entry_id,
364 service_->AddToList(url,
365 service_->CreateDefaultDistillerPage().Pass(),
366 ArticleCallback(&article_cb[i])));
369 base::RunLoop().RunUntilIdle();
372 TEST_F(DomDistillerServiceTest, TestMultipleCallbacksOnRemove) {
373 FakeDistiller* distiller = new FakeDistiller(false);
374 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
375 .WillOnce(Return(distiller));
377 const int kClientsCount = 5;
378 MockArticleAvailableCallback article_cb[kClientsCount];
379 // Adding a URL and remove the entry before distillation. Callback should be
380 // called with false.
381 GURL url("http://www.example.com/p1");
382 const std::string entry_id =
383 service_->AddToList(url,
384 service_->CreateDefaultDistillerPage().Pass(),
385 ArticleCallback(&article_cb[0]));
387 EXPECT_CALL(article_cb[0], DistillationCompleted(false));
388 for (int i = 1; i < kClientsCount; ++i) {
389 EXPECT_EQ(entry_id,
390 service_->AddToList(url,
391 service_->CreateDefaultDistillerPage().Pass(),
392 ArticleCallback(&article_cb[i])));
393 EXPECT_CALL(article_cb[i], DistillationCompleted(false));
396 service_->RemoveEntry(entry_id);
397 base::RunLoop().RunUntilIdle();
400 TEST_F(DomDistillerServiceTest, TestMultiplePageArticle) {
401 FakeDistiller* distiller = new FakeDistiller(false);
402 EXPECT_CALL(*distiller_factory_, CreateDistillerImpl())
403 .WillOnce(Return(distiller));
405 const int kPageCount = 8;
407 std::string base_url("http://www.example.com/p");
408 GURL pages_url[kPageCount];
409 for (int page_num = 0; page_num < kPageCount; ++page_num) {
410 pages_url[page_num] = GURL(base_url + base::IntToString(page_num));
413 MockArticleAvailableCallback article_cb;
414 EXPECT_CALL(article_cb, DistillationCompleted(true));
416 std::string entry_id =
417 service_->AddToList(pages_url[0],
418 service_->CreateDefaultDistillerPage().Pass(),
419 ArticleCallback(&article_cb));
421 ArticleEntry entry;
422 ASSERT_FALSE(distiller->GetArticleCallback().is_null());
423 EXPECT_EQ(pages_url[0], distiller->GetUrl());
425 // Create the article with pages to pass to the distiller.
426 scoped_ptr<DistilledArticleProto> proto =
427 CreateArticleWithURL(pages_url[0].spec());
428 for (int page_num = 1; page_num < kPageCount; ++page_num) {
429 DistilledPageProto* distilled_page = proto->add_pages();
430 distilled_page->set_url(pages_url[page_num].spec());
433 RunDistillerCallback(distiller, proto.Pass());
434 EXPECT_TRUE(store_->GetEntryByUrl(pages_url[0], &entry));
436 EXPECT_EQ(kPageCount, entry.pages_size());
437 // An article should have just one entry.
438 EXPECT_EQ(1u, store_->GetEntries().size());
440 // All pages should have correct urls.
441 for (int page_num = 0; page_num < kPageCount; ++page_num) {
442 EXPECT_EQ(pages_url[page_num].spec(), entry.pages(page_num).url());
445 // Should be able to query article using any of the pages url.
446 for (int page_num = 0; page_num < kPageCount; ++page_num) {
447 EXPECT_TRUE(store_->GetEntryByUrl(pages_url[page_num], &entry));
450 service_->RemoveEntry(entry_id);
451 base::RunLoop().RunUntilIdle();
452 EXPECT_EQ(0u, store_->GetEntries().size());
455 } // namespace test
456 } // namespace dom_distiller