| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/dom_distiller/core/dom_distiller_service.h" |
| |
| #include "base/bind.h" |
| #include "base/containers/hash_tables.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| #include "components/dom_distiller/core/article_entry.h" |
| #include "components/dom_distiller/core/dom_distiller_model.h" |
| #include "components/dom_distiller/core/dom_distiller_store.h" |
| #include "components/dom_distiller/core/fake_distiller.h" |
| #include "components/dom_distiller/core/task_tracker.h" |
| #include "testing/gmock/include/gmock/gmock.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using testing::Invoke; |
| using testing::Return; |
| using testing::_; |
| |
| namespace dom_distiller { |
| namespace test { |
| |
| namespace { |
| |
| class FakeDomDistillerStore : public DomDistillerStoreInterface { |
| public: |
| virtual ~FakeDomDistillerStore() {} |
| |
| virtual bool AddEntry(const ArticleEntry& entry) OVERRIDE { |
| if (!IsEntryValid(entry)) { |
| return false; |
| } |
| |
| if (model_.GetEntryById(entry.entry_id(), NULL)) { |
| return false; |
| } |
| |
| syncer::SyncChangeList changes_to_apply; |
| syncer::SyncChangeList changes_applied; |
| syncer::SyncChangeList changes_missing; |
| |
| changes_to_apply.push_back(syncer::SyncChange( |
| FROM_HERE, syncer::SyncChange::ACTION_ADD, CreateLocalData(entry))); |
| |
| model_.ApplyChangesToModel( |
| changes_to_apply, &changes_applied, &changes_missing); |
| |
| return true; |
| } |
| |
| virtual bool RemoveEntry(const ArticleEntry& entry) OVERRIDE { |
| if (!IsEntryValid(entry)) { |
| return false; |
| } |
| |
| if (!model_.GetEntryById(entry.entry_id(), NULL)) { |
| return false; |
| } |
| |
| syncer::SyncChangeList changes_to_apply; |
| syncer::SyncChangeList changes_applied; |
| syncer::SyncChangeList changes_missing; |
| |
| changes_to_apply.push_back(syncer::SyncChange( |
| FROM_HERE, syncer::SyncChange::ACTION_DELETE, CreateLocalData(entry))); |
| |
| model_.ApplyChangesToModel( |
| changes_to_apply, &changes_applied, &changes_missing); |
| |
| return true; |
| } |
| |
| virtual bool GetEntryById(const std::string& entry_id, |
| ArticleEntry* entry) OVERRIDE { |
| return model_.GetEntryById(entry_id, entry); |
| } |
| |
| virtual bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) OVERRIDE { |
| return model_.GetEntryByUrl(url, entry); |
| } |
| |
| // Gets a copy of all the current entries. |
| virtual std::vector<ArticleEntry> GetEntries() const OVERRIDE { |
| return model_.GetEntries(); |
| } |
| |
| virtual syncer::SyncableService* GetSyncableService() OVERRIDE { |
| return NULL; |
| } |
| |
| virtual void AddObserver(DomDistillerObserver* observer) OVERRIDE {} |
| virtual void RemoveObserver(DomDistillerObserver* observer) OVERRIDE {} |
| |
| private: |
| DomDistillerModel model_; |
| }; |
| |
| class FakeViewRequestDelegate : public ViewRequestDelegate { |
| public: |
| virtual ~FakeViewRequestDelegate() {} |
| MOCK_METHOD1(OnArticleReady, void(DistilledPageProto* proto)); |
| }; |
| |
| } // namespace |
| |
| class DomDistillerServiceTest : public testing::Test { |
| public: |
| virtual void SetUp() { |
| main_loop_.reset(new base::MessageLoop()); |
| store_ = new FakeDomDistillerStore(); |
| distiller_factory_ = new MockDistillerFactory(); |
| service_.reset(new DomDistillerService( |
| scoped_ptr<DomDistillerStoreInterface>(store_), |
| scoped_ptr<DistillerFactory>(distiller_factory_))); |
| } |
| |
| virtual void TearDown() { |
| base::RunLoop().RunUntilIdle(); |
| store_ = NULL; |
| distiller_factory_ = NULL; |
| service_.reset(); |
| } |
| |
| protected: |
| FakeDomDistillerStore* store_; |
| MockDistillerFactory* distiller_factory_; |
| scoped_ptr<DomDistillerService> service_; |
| scoped_ptr<base::MessageLoop> main_loop_; |
| }; |
| |
| TEST_F(DomDistillerServiceTest, TestViewEntry) { |
| FakeDistiller* distiller = new FakeDistiller(); |
| EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) |
| .WillOnce(Return(distiller)); |
| |
| GURL url("http://www.example.com/p1"); |
| std::string entry_id("id0"); |
| ArticleEntry entry; |
| entry.set_entry_id(entry_id); |
| entry.add_pages()->set_url(url.spec()); |
| |
| store_->AddEntry(entry); |
| |
| FakeViewRequestDelegate viewer_delegate; |
| scoped_ptr<ViewerHandle> handle = |
| service_->ViewEntry(&viewer_delegate, entry_id); |
| |
| ASSERT_FALSE(distiller->GetCallback().is_null()); |
| |
| scoped_ptr<DistilledPageProto> proto(new DistilledPageProto); |
| EXPECT_CALL(viewer_delegate, OnArticleReady(proto.get())); |
| |
| distiller->RunDistillerCallback(proto.Pass()); |
| } |
| |
| TEST_F(DomDistillerServiceTest, TestViewUrl) { |
| FakeDistiller* distiller = new FakeDistiller(); |
| EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) |
| .WillOnce(Return(distiller)); |
| |
| FakeViewRequestDelegate viewer_delegate; |
| GURL url("http://www.example.com/p1"); |
| scoped_ptr<ViewerHandle> handle = service_->ViewUrl(&viewer_delegate, url); |
| |
| ASSERT_FALSE(distiller->GetCallback().is_null()); |
| EXPECT_EQ(url, distiller->GetUrl()); |
| |
| scoped_ptr<DistilledPageProto> proto(new DistilledPageProto); |
| EXPECT_CALL(viewer_delegate, OnArticleReady(proto.get())); |
| |
| distiller->RunDistillerCallback(proto.Pass()); |
| } |
| |
| TEST_F(DomDistillerServiceTest, TestMultipleViewUrl) { |
| FakeDistiller* distiller = new FakeDistiller(); |
| FakeDistiller* distiller2 = new FakeDistiller(); |
| EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) |
| .WillOnce(Return(distiller)) |
| .WillOnce(Return(distiller2)); |
| |
| FakeViewRequestDelegate viewer_delegate; |
| FakeViewRequestDelegate viewer_delegate2; |
| |
| GURL url("http://www.example.com/p1"); |
| GURL url2("http://www.example.com/a/p1"); |
| |
| scoped_ptr<ViewerHandle> handle = service_->ViewUrl(&viewer_delegate, url); |
| scoped_ptr<ViewerHandle> handle2 = service_->ViewUrl(&viewer_delegate2, url2); |
| |
| ASSERT_FALSE(distiller->GetCallback().is_null()); |
| EXPECT_EQ(url, distiller->GetUrl()); |
| |
| scoped_ptr<DistilledPageProto> proto(new DistilledPageProto); |
| EXPECT_CALL(viewer_delegate, OnArticleReady(proto.get())); |
| |
| distiller->RunDistillerCallback(proto.Pass()); |
| |
| ASSERT_FALSE(distiller2->GetCallback().is_null()); |
| EXPECT_EQ(url2, distiller2->GetUrl()); |
| |
| scoped_ptr<DistilledPageProto> proto2(new DistilledPageProto); |
| EXPECT_CALL(viewer_delegate2, OnArticleReady(proto2.get())); |
| |
| distiller2->RunDistillerCallback(proto2.Pass()); |
| } |
| |
| TEST_F(DomDistillerServiceTest, TestViewUrlCancelled) { |
| FakeDistiller* distiller = new FakeDistiller(); |
| EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) |
| .WillOnce(Return(distiller)); |
| |
| bool distiller_destroyed = false; |
| EXPECT_CALL(*distiller, Die()) |
| .WillOnce(testing::Assign(&distiller_destroyed, true)); |
| |
| FakeViewRequestDelegate viewer_delegate; |
| GURL url("http://www.example.com/p1"); |
| scoped_ptr<ViewerHandle> handle = service_->ViewUrl(&viewer_delegate, url); |
| |
| ASSERT_FALSE(distiller->GetCallback().is_null()); |
| EXPECT_EQ(url, distiller->GetUrl()); |
| |
| EXPECT_CALL(viewer_delegate, OnArticleReady(_)).Times(0); |
| |
| EXPECT_FALSE(distiller_destroyed); |
| |
| handle.reset(); |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_TRUE(distiller_destroyed); |
| } |
| |
| TEST_F(DomDistillerServiceTest, TestAddAndRemoveEntry) { |
| FakeDistiller* distiller = new FakeDistiller(); |
| EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) |
| .WillOnce(Return(distiller)); |
| |
| GURL url("http://www.example.com/p1"); |
| |
| service_->AddToList(url); |
| |
| ASSERT_FALSE(distiller->GetCallback().is_null()); |
| EXPECT_EQ(url, distiller->GetUrl()); |
| |
| scoped_ptr<DistilledPageProto> proto(new DistilledPageProto); |
| distiller->RunDistillerCallback(proto.Pass()); |
| |
| ArticleEntry entry; |
| EXPECT_TRUE(store_->GetEntryByUrl(url, &entry)); |
| EXPECT_EQ(1u, store_->GetEntries().size()); |
| store_->RemoveEntry(entry); |
| EXPECT_EQ(0u, store_->GetEntries().size()); |
| |
| } |
| |
| |
| } // namespace test |
| } // namespace dom_distiller |