| Index: components/dom_distiller/core/distilled_content_store_unittest.cc
|
| diff --git a/components/dom_distiller/core/distilled_content_store_unittest.cc b/components/dom_distiller/core/distilled_content_store_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5bab00e0dcf78818826dedbbe03deb2b311cea1b
|
| --- /dev/null
|
| +++ b/components/dom_distiller/core/distilled_content_store_unittest.cc
|
| @@ -0,0 +1,243 @@
|
| +// Copyright 2014 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 "base/bind.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/distilled_content_store.h"
|
| +#include "components/dom_distiller/core/proto/distilled_article.pb.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +
|
| +namespace dom_distiller {
|
| +
|
| +namespace {
|
| +
|
| +ArticleEntry CreateEntry(std::string entry_id,
|
| + std::string page_url1,
|
| + std::string page_url2,
|
| + std::string page_url3) {
|
| + ArticleEntry entry;
|
| + entry.set_entry_id(entry_id);
|
| + if (!page_url1.empty()) {
|
| + ArticleEntryPage* page = entry.add_pages();
|
| + page->set_url(page_url1);
|
| + }
|
| + if (!page_url2.empty()) {
|
| + ArticleEntryPage* page = entry.add_pages();
|
| + page->set_url(page_url2);
|
| + }
|
| + if (!page_url3.empty()) {
|
| + ArticleEntryPage* page = entry.add_pages();
|
| + page->set_url(page_url3);
|
| + }
|
| + return entry;
|
| +}
|
| +
|
| +DistilledArticleProto CreateDistilledArticleForEntry(
|
| + const ArticleEntry& entry) {
|
| + DistilledArticleProto article;
|
| + for (int i = 0; i < entry.pages_size(); ++i) {
|
| + DistilledPageProto* page = article.add_pages();
|
| + page->set_url(entry.pages(i).url());
|
| + page->set_html("<div>" + entry.pages(i).url() + "</div>");
|
| + }
|
| + return article;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +class InMemoryContentStoreTest : public testing::Test {
|
| + public:
|
| + void OnLoadCallback(bool success, scoped_ptr<DistilledArticleProto> proto) {
|
| + load_success_ = success;
|
| + loaded_proto_ = proto.Pass();
|
| + }
|
| +
|
| + void OnSaveCallback(bool success) { save_success_ = success; }
|
| +
|
| + protected:
|
| + // testing::Test implementation:
|
| + virtual void SetUp() OVERRIDE {
|
| + store_.reset(new InMemoryContentStore(kDefaultMaxNumCachedEntries));
|
| + save_success_ = false;
|
| + load_success_ = false;
|
| + loaded_proto_.reset();
|
| + }
|
| +
|
| + scoped_ptr<InMemoryContentStore> store_;
|
| + bool save_success_;
|
| + bool load_success_;
|
| + scoped_ptr<DistilledArticleProto> loaded_proto_;
|
| +};
|
| +
|
| +// Tests whether saving and then loading a single article works as expected.
|
| +TEST_F(InMemoryContentStoreTest, SaveAndLoadSingleArticle) {
|
| + base::MessageLoop loop;
|
| + const ArticleEntry entry = CreateEntry("test-id", "url1", "url2", "url3");
|
| + const DistilledArticleProto stored_proto =
|
| + CreateDistilledArticleForEntry(entry);
|
| + store_->SaveContent(entry,
|
| + stored_proto,
|
| + base::Bind(&InMemoryContentStoreTest::OnSaveCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(save_success_);
|
| + save_success_ = false;
|
| +
|
| + store_->LoadContent(entry,
|
| + base::Bind(&InMemoryContentStoreTest::OnLoadCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(load_success_);
|
| + EXPECT_EQ(stored_proto.SerializeAsString(),
|
| + loaded_proto_->SerializeAsString());
|
| +}
|
| +
|
| +// Tests that loading articles which have never been stored, yields a callback
|
| +// where success is false.
|
| +TEST_F(InMemoryContentStoreTest, LoadNonExistentArticle) {
|
| + base::MessageLoop loop;
|
| + const ArticleEntry entry = CreateEntry("bogus-id", "url1", "url2", "url3");
|
| + store_->LoadContent(entry,
|
| + base::Bind(&InMemoryContentStoreTest::OnLoadCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_FALSE(load_success_);
|
| +}
|
| +
|
| +// Verifies that content store can store multiple articles, and that ordering
|
| +// of save and store does not matter when the total number of articles does not
|
| +// exceed |kDefaultMaxNumCachedEntries|.
|
| +TEST_F(InMemoryContentStoreTest, SaveAndLoadMultipleArticles) {
|
| + base::MessageLoop loop;
|
| + // Store first article.
|
| + const ArticleEntry first_entry = CreateEntry("first", "url1", "url2", "url3");
|
| + const DistilledArticleProto first_stored_proto =
|
| + CreateDistilledArticleForEntry(first_entry);
|
| + store_->SaveContent(first_entry,
|
| + first_stored_proto,
|
| + base::Bind(&InMemoryContentStoreTest::OnSaveCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(save_success_);
|
| + save_success_ = false;
|
| +
|
| + // Store second article.
|
| + const ArticleEntry second_entry =
|
| + CreateEntry("second", "url1", "url2", "url3");
|
| + const DistilledArticleProto second_stored_proto =
|
| + CreateDistilledArticleForEntry(second_entry);
|
| + store_->SaveContent(second_entry,
|
| + second_stored_proto,
|
| + base::Bind(&InMemoryContentStoreTest::OnSaveCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(save_success_);
|
| + save_success_ = false;
|
| +
|
| + // Load second article.
|
| + store_->LoadContent(second_entry,
|
| + base::Bind(&InMemoryContentStoreTest::OnLoadCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(load_success_);
|
| + load_success_ = false;
|
| + EXPECT_EQ(second_stored_proto.SerializeAsString(),
|
| + loaded_proto_->SerializeAsString());
|
| + loaded_proto_.reset();
|
| +
|
| + // Load first article.
|
| + store_->LoadContent(first_entry,
|
| + base::Bind(&InMemoryContentStoreTest::OnLoadCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(load_success_);
|
| + EXPECT_EQ(first_stored_proto.SerializeAsString(),
|
| + loaded_proto_->SerializeAsString());
|
| +}
|
| +
|
| +// Verifies that the content store does not store unlimited number of articles,
|
| +// but expires the oldest ones when the limit for number of articles is reached.
|
| +TEST_F(InMemoryContentStoreTest, SaveAndLoadMoreThanMaxArticles) {
|
| + base::MessageLoop loop;
|
| +
|
| + // Create a new store with only |kMaxNumArticles| articles as the limit.
|
| + const int kMaxNumArticles = 3;
|
| + store_.reset(new InMemoryContentStore(kMaxNumArticles));
|
| +
|
| + // Store first article.
|
| + const ArticleEntry first_entry = CreateEntry("first", "url1", "url2", "url3");
|
| + const DistilledArticleProto first_stored_proto =
|
| + CreateDistilledArticleForEntry(first_entry);
|
| + store_->SaveContent(first_entry,
|
| + first_stored_proto,
|
| + base::Bind(&InMemoryContentStoreTest::OnSaveCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(save_success_);
|
| + save_success_ = false;
|
| +
|
| + // Store second article.
|
| + const ArticleEntry second_entry =
|
| + CreateEntry("second", "url1", "url2", "url3");
|
| + const DistilledArticleProto second_stored_proto =
|
| + CreateDistilledArticleForEntry(second_entry);
|
| + store_->SaveContent(second_entry,
|
| + second_stored_proto,
|
| + base::Bind(&InMemoryContentStoreTest::OnSaveCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(save_success_);
|
| + save_success_ = false;
|
| +
|
| + // Store third article.
|
| + const ArticleEntry third_entry = CreateEntry("third", "url1", "url2", "url3");
|
| + const DistilledArticleProto third_stored_proto =
|
| + CreateDistilledArticleForEntry(third_entry);
|
| + store_->SaveContent(third_entry,
|
| + third_stored_proto,
|
| + base::Bind(&InMemoryContentStoreTest::OnSaveCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(save_success_);
|
| + save_success_ = false;
|
| +
|
| + // Load first article. This will make the first article the most recent
|
| + // accessed article.
|
| + store_->LoadContent(first_entry,
|
| + base::Bind(&InMemoryContentStoreTest::OnLoadCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(load_success_);
|
| + load_success_ = false;
|
| + EXPECT_EQ(first_stored_proto.SerializeAsString(),
|
| + loaded_proto_->SerializeAsString());
|
| + loaded_proto_.reset();
|
| +
|
| + // Store fourth article.
|
| + const ArticleEntry fourth_entry =
|
| + CreateEntry("fourth", "url1", "url2", "url3");
|
| + const DistilledArticleProto fourth_stored_proto =
|
| + CreateDistilledArticleForEntry(fourth_entry);
|
| + store_->SaveContent(fourth_entry,
|
| + fourth_stored_proto,
|
| + base::Bind(&InMemoryContentStoreTest::OnSaveCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + EXPECT_TRUE(save_success_);
|
| + save_success_ = false;
|
| +
|
| + // Load second article, which by now is the oldest accessed article, since
|
| + // the first article has been loaded once.
|
| + store_->LoadContent(second_entry,
|
| + base::Bind(&InMemoryContentStoreTest::OnLoadCallback,
|
| + base::Unretained(this)));
|
| + base::MessageLoop::current()->RunUntilIdle();
|
| + // Since the store can only contain |kMaxNumArticles| entries, this load
|
| + // should fail.
|
| + EXPECT_FALSE(load_success_);
|
| +}
|
| +
|
| +} // namespace dom_distiller
|
|
|