Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Unified Diff: components/download/internal/model_impl_unittest.cc

Issue 2870753003: Add a Model to the download component. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/download/internal/model_impl_unittest.cc
diff --git a/components/download/internal/model_impl_unittest.cc b/components/download/internal/model_impl_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..1665a8968aabe175cfd4e303f8784c6d8043d3ff
--- /dev/null
+++ b/components/download/internal/model_impl_unittest.cc
@@ -0,0 +1,318 @@
+// Copyright 2017 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/download/internal/model_impl.h"
+
+#include "base/bind.h"
+#include "base/guid.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "components/download/internal/entry.h"
+#include "components/download/internal/noop_store.h"
+#include "components/download/internal/test_support/mock_model_client.h"
+#include "components/download/internal/test_support/mock_store.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::Return;
+using testing::_;
+
+namespace download {
+namespace {
+
+class BadStore : public Store {
+ public:
+ BadStore() = default;
+ ~BadStore() override = default;
+
+ // Store implementation.
+ MOCK_METHOD0(IsInitialized, bool());
+ void Initialize(const InitCallback& callback) override {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, false, nullptr));
+ }
+
+ void Destroy(const StoreCallback& callback) override {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback, false));
+ }
+
+ void Update(const Entry& entry, const StoreCallback& callback) override {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback, false));
+ }
+
+ void Remove(const std::string& guid, const StoreCallback& callback) override {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback, false));
+ }
+};
+
+struct CompareByGuid {
+ bool operator()(const Entry* a, const Entry* b) const {
+ return a->guid < b->guid;
+ }
+};
+
+template <typename T>
+bool VectorContentsEq(const std::vector<T>& list1,
+ const std::vector<T>& list2) {
+ if (list1.size() != list2.size())
+ return false;
+
+ std::map<T, int, CompareByGuid> occurance_counts;
+ for (auto it = list1.begin(); it != list1.end(); it++)
+ occurance_counts[*it]++;
+
+ for (auto it = list2.begin(); it != list2.end(); it++)
+ occurance_counts[*it]--;
+
+ for (auto it = occurance_counts.begin(); it != occurance_counts.end(); it++) {
+ if (it->second != 0)
+ return false;
+ }
+
+ return true;
Peter Beverloo 2017/05/10 12:44:45 I think you could *significantly* simplify this (a
David Trainor- moved to gerrit 2017/05/15 15:59:51 O_o! Yeah way better :).
+}
+
+Entry BuildEntry(DownloadClient client, const std::string& guid) {
+ Entry entry;
+ entry.client = client;
+ entry.guid = guid;
+
+ return entry;
+}
+
+bool CompareEntryBasics(const Entry& expected, const Entry* const actual) {
+ return actual != nullptr && expected.client == actual->client &&
+ expected.guid == actual->guid && expected.state == actual->state;
+}
+
+class ModelImplStoreTestBase : public testing::Test {
+ public:
+ ModelImplStoreTestBase(Store* store)
+ : task_runner_(new base::TestMockTimeTaskRunner),
Peter Beverloo 2017/05/10 12:44:45 qq: would TestSimpleTaskRunner suffice? why is tim
David Trainor- moved to gerrit 2017/05/15 15:59:51 Good call. Done.
+ handle_(task_runner_),
+ store_(store),
+ model_(base::MakeUnique<ModelImpl>(&client_,
+ base::WrapUnique<Store>(store))) {}
+
+ ~ModelImplStoreTestBase() override = default;
+
+ protected:
+ scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
+ base::ThreadTaskRunnerHandle handle_;
+ MockModelClient client_;
+ Store* store_;
+ std::unique_ptr<ModelImpl> model_;
+};
+
+class ModelImplNoopStoreTest : public ModelImplStoreTestBase {
+ public:
+ ModelImplNoopStoreTest() : ModelImplStoreTestBase(new NoopStore) {}
+};
+
+class ModelImplMockStoreTest : public ModelImplStoreTestBase {
+ public:
+ ModelImplMockStoreTest()
+ : ModelImplStoreTestBase(new MockStore),
+ mocked_store_(static_cast<MockStore*>(store_)) {}
+
+ protected:
+ MockStore* mocked_store_;
+};
+
+class ModelImplBadStoreTest : public ModelImplStoreTestBase {
+ public:
+ ModelImplBadStoreTest()
+ : ModelImplStoreTestBase(new BadStore),
+ mocked_store_(static_cast<BadStore*>(store_)) {}
+
+ protected:
+ BadStore* mocked_store_;
+};
+
+TEST_F(ModelImplNoopStoreTest, Lifecycle) {
+ EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+ model_->Initialize();
+ task_runner_->RunUntilIdle();
+
+ EXPECT_CALL(client_, OnDestroyed(true)).Times(1);
+ model_->Destroy();
+ task_runner_->RunUntilIdle();
+}
+
+TEST_F(ModelImplNoopStoreTest, Add) {
+ EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+ model_->Initialize();
+ task_runner_->RunUntilIdle();
+
+ std::string guid1 = base::GenerateGUID();
+ std::string guid2 = base::GenerateGUID();
+
+ DownloadClient client1 = DownloadClient::TEST_1;
+ DownloadClient client2 = DownloadClient::TEST_2;
+
+ Entry entry1 = BuildEntry(client1, guid1);
+ Entry entry2 = BuildEntry(client2, guid2);
+
+ EXPECT_CALL(client_, OnItemAdded(true, client1, guid1)).Times(1);
+ EXPECT_CALL(client_, OnItemAdded(true, client2, guid2)).Times(1);
+
+ EXPECT_EQ(nullptr, model_->Get(guid1));
+ EXPECT_EQ(nullptr, model_->Get(guid2));
+
+ model_->Add(entry1);
+ model_->Add(entry2);
+
+ // Validate that the new item is available immediately after adding.
+ EXPECT_TRUE(CompareEntryBasics(entry1, model_->Get(guid1)));
+ EXPECT_TRUE(CompareEntryBasics(entry2, model_->Get(guid2)));
+
+ task_runner_->RunUntilIdle();
+}
+
+TEST_F(ModelImplNoopStoreTest, Update) {
+ EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+ model_->Initialize();
+ task_runner_->RunUntilIdle();
+
+ std::string guid = base::GenerateGUID();
+ DownloadClient client = DownloadClient::TEST_1;
+
+ Entry entry1 = BuildEntry(client, guid);
+ Entry entry2(entry1);
+
+ entry1.state = Entry::State::NEW;
+ entry2.state = Entry::State::ACTIVE;
+
+ EXPECT_CALL(client_, OnItemAdded(true, client, guid)).Times(1);
+
+ EXPECT_EQ(nullptr, model_->Get(guid));
+
+ model_->Add(entry1);
+ task_runner_->RunUntilIdle();
+
+ EXPECT_TRUE(CompareEntryBasics(entry1, model_->Get(guid)));
+
+ model_->Update(entry2);
+
+ // Validate that the updated item is available immediately after updating.
+ EXPECT_TRUE(CompareEntryBasics(entry2, model_->Get(guid)));
+
+ task_runner_->RunUntilIdle();
+}
+
+TEST_F(ModelImplNoopStoreTest, Remove) {
+ EXPECT_CALL(client_, OnInitialized(true)).Times(1);
+ model_->Initialize();
+ task_runner_->RunUntilIdle();
+
+ std::string guid = base::GenerateGUID();
+
+ DownloadClient client = DownloadClient::TEST_1;
+
+ Entry entry = BuildEntry(client, guid);
+
+ EXPECT_CALL(client_, OnItemAdded(true, client, guid)).Times(1);
+
+ EXPECT_EQ(nullptr, model_->Get(guid));
+
+ model_->Add(entry);
+ task_runner_->RunUntilIdle();
+
+ EXPECT_TRUE(CompareEntryBasics(entry, model_->Get(guid)));
+
+ model_->Remove(guid);
+
+ // Validate that the removed item is unavailable immediately after updating.
+ EXPECT_EQ(nullptr, model_->Get(guid));
+
+ task_runner_->RunUntilIdle();
+}
+
+TEST_F(ModelImplNoopStoreTest, Get) {
+ model_->Initialize();
+ task_runner_->RunUntilIdle();
+
+ std::string guid = base::GenerateGUID();
+ Entry entry = BuildEntry(DownloadClient::TEST_1, guid);
+
+ model_->Add(entry);
+ task_runner_->RunUntilIdle();
+
+ EXPECT_TRUE(CompareEntryBasics(entry, model_->Get(guid)));
+}
+
+TEST_F(ModelImplNoopStoreTest, PeekEntries) {
+ model_->Initialize();
+ task_runner_->RunUntilIdle();
+
+ std::string guid1 = base::GenerateGUID();
+ std::string guid2 = base::GenerateGUID();
+ std::string guid3 = base::GenerateGUID();
+
+ Entry entry1 = BuildEntry(DownloadClient::TEST_1, guid1);
+ Entry entry2 = BuildEntry(DownloadClient::TEST_2, guid2);
+ Entry entry3 = BuildEntry(DownloadClient::TEST_3, guid3);
+
+ Model::EntryList entries = {&entry1, &entry2, &entry3};
+
+ model_->Add(entry1);
+ model_->Add(entry2);
+ model_->Add(entry3);
+ task_runner_->RunUntilIdle();
+
+ EXPECT_TRUE(VectorContentsEq(entries, model_->PeekEntries()));
+}
+
+TEST_F(ModelImplMockStoreTest, TestStoreCalls) {
+ {
+ EXPECT_CALL(*mocked_store_, IsInitialized()).WillRepeatedly(Return(false));
+ EXPECT_CALL(*mocked_store_, Initialize(_)).Times(1);
+ model_->Initialize();
+ }
+
+ EXPECT_CALL(*mocked_store_, IsInitialized()).WillRepeatedly(Return(true));
+
+ std::string guid = base::GenerateGUID();
+ Entry entry = BuildEntry(DownloadClient::TEST_1, guid);
+
+ EXPECT_CALL(*mocked_store_, Update(_, _)).Times(2);
+ EXPECT_CALL(*mocked_store_, Remove(guid, _)).Times(1);
+ EXPECT_CALL(*mocked_store_, Destroy(_)).Times(1);
+
+ model_->Add(entry);
+ model_->Update(entry);
+ model_->Remove(guid);
+ model_->Destroy();
+}
+
+TEST_F(ModelImplBadStoreTest, ModelUpdatesFailed) {
+ {
+ EXPECT_CALL(*mocked_store_, IsInitialized()).WillRepeatedly(Return(false));
+ EXPECT_CALL(client_, OnInitialized(false)).Times(1);
+ model_->Initialize();
+ }
+
+ EXPECT_CALL(*mocked_store_, IsInitialized()).WillRepeatedly(Return(true));
+
+ std::string guid = base::GenerateGUID();
+ DownloadClient client = DownloadClient::TEST_1;
+ Entry entry = BuildEntry(client, guid);
+
+ EXPECT_CALL(client_, OnItemAdded(false, client, guid)).Times(1);
+ EXPECT_CALL(client_, OnStoreUpdateFailed(client, guid)).Times(2);
+ EXPECT_CALL(client_, OnDestroyed(false));
+
+ model_->Add(entry);
+ model_->Update(entry);
+ model_->Remove(guid);
+ model_->Destroy();
+
+ task_runner_->RunUntilIdle();
+}
+
+} // namespace
+} // namespace download

Powered by Google App Engine
This is Rietveld 408576698