1 // Copyright 2015 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/offline_pages/offline_page_metadata_store_impl.h"
8 #include "base/files/file_path.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "components/leveldb_proto/proto_database_impl.h"
15 #include "components/offline_pages/offline_page_item.h"
16 #include "components/offline_pages/proto/offline_pages.pb.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using leveldb_proto::ProtoDatabaseImpl
;
21 namespace offline_pages
{
25 const char kTestURL
[] = "https://example.com";
26 const int64 kTestBookmarkId
= 1234LL;
27 const base::FilePath::CharType kFilePath
[] =
28 FILE_PATH_LITERAL("/offline_pages/example_com.mhtml");
29 int64 kFileSize
= 234567;
31 class OfflinePageMetadataStoreImplTest
: public testing::Test
{
33 enum CalledCallback
{ NONE
, LOAD
, ADD
, REMOVE
, DESTROY
};
34 enum Status
{ STATUS_NONE
, STATUS_TRUE
, STATUS_FALSE
};
36 OfflinePageMetadataStoreImplTest();
37 ~OfflinePageMetadataStoreImplTest() override
;
39 void TearDown() override
{ message_loop_
.RunUntilIdle(); }
41 scoped_ptr
<OfflinePageMetadataStoreImpl
> BuildStore();
44 void LoadCallback(bool success
,
45 const std::vector
<OfflinePageItem
>& offline_pages
);
46 void UpdateCallback(CalledCallback called_callback
, bool success
);
51 CalledCallback last_called_callback_
;
53 std::vector
<OfflinePageItem
> offline_pages_
;
55 base::ScopedTempDir temp_directory_
;
56 base::MessageLoop message_loop_
;
57 scoped_ptr
<base::RunLoop
> run_loop_
;
60 OfflinePageMetadataStoreImplTest::OfflinePageMetadataStoreImplTest()
61 : last_called_callback_(NONE
), last_status_(STATUS_NONE
) {
62 EXPECT_TRUE(temp_directory_
.CreateUniqueTempDir());
65 OfflinePageMetadataStoreImplTest::~OfflinePageMetadataStoreImplTest() {
68 void OfflinePageMetadataStoreImplTest::PumpLoop() {
69 run_loop_
.reset(new base::RunLoop());
73 scoped_ptr
<OfflinePageMetadataStoreImpl
>
74 OfflinePageMetadataStoreImplTest::BuildStore() {
75 scoped_ptr
<ProtoDatabaseImpl
<offline_pages::OfflinePageEntry
>> db(
76 new ProtoDatabaseImpl
<offline_pages::OfflinePageEntry
>(
77 message_loop_
.task_runner()));
78 return scoped_ptr
<OfflinePageMetadataStoreImpl
>(
79 new OfflinePageMetadataStoreImpl(db
.Pass(), temp_directory_
.path()));
82 void OfflinePageMetadataStoreImplTest::LoadCallback(
84 const std::vector
<OfflinePageItem
>& offline_pages
) {
85 last_called_callback_
= LOAD
;
86 last_status_
= status
? STATUS_TRUE
: STATUS_FALSE
;
87 offline_pages_
.swap(const_cast<std::vector
<OfflinePageItem
>&>(offline_pages
));
91 void OfflinePageMetadataStoreImplTest::UpdateCallback(
92 CalledCallback called_callback
,
94 last_called_callback_
= called_callback
;
95 last_status_
= status
? STATUS_TRUE
: STATUS_FALSE
;
99 void OfflinePageMetadataStoreImplTest::ClearResults() {
100 last_called_callback_
= NONE
;
101 last_status_
= STATUS_NONE
;
102 offline_pages_
.clear();
105 // Loads empty store and makes sure that there are no offline pages stored in
107 TEST_F(OfflinePageMetadataStoreImplTest
, LoadEmptyStore
) {
108 scoped_ptr
<OfflinePageMetadataStoreImpl
> store(BuildStore());
109 store
->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback
,
110 base::Unretained(this)));
113 EXPECT_EQ(LOAD
, last_called_callback_
);
114 EXPECT_EQ(STATUS_TRUE
, last_status_
);
115 EXPECT_EQ(0U, offline_pages_
.size());
118 // Adds metadata of an offline page into a store and then loads from the
119 // store to make sure the metadata is preserved.
120 TEST_F(OfflinePageMetadataStoreImplTest
, AddOfflinePageThenLoad
) {
121 scoped_ptr
<OfflinePageMetadataStoreImpl
> store(BuildStore());
123 OfflinePageItem
offline_page(GURL(kTestURL
), kTestBookmarkId
,
124 base::FilePath(kFilePath
), kFileSize
);
125 store
->AddOfflinePage(
127 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback
,
128 base::Unretained(this), ADD
));
130 EXPECT_EQ(ADD
, last_called_callback_
);
131 EXPECT_EQ(STATUS_TRUE
, last_status_
);
134 store
->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback
,
135 base::Unretained(this)));
138 EXPECT_EQ(LOAD
, last_called_callback_
);
139 EXPECT_EQ(STATUS_TRUE
, last_status_
);
140 EXPECT_EQ(1U, offline_pages_
.size());
141 EXPECT_EQ(offline_page
.url
, offline_pages_
[0].url
);
142 EXPECT_EQ(offline_page
.bookmark_id
, offline_pages_
[0].bookmark_id
);
143 EXPECT_EQ(offline_page
.version
, offline_pages_
[0].version
);
144 EXPECT_EQ(offline_page
.file_path
, offline_pages_
[0].file_path
);
145 EXPECT_EQ(offline_page
.file_size
, offline_pages_
[0].file_size
);
146 EXPECT_EQ(offline_page
.creation_time
, offline_pages_
[0].creation_time
);
147 EXPECT_EQ(offline_page
.last_access_time
, offline_pages_
[0].last_access_time
);
150 // Adds metadata of an offline page into a store and then opens the store
151 // again to make sure that stored metadata survives store restarts.
152 TEST_F(OfflinePageMetadataStoreImplTest
, AddOfflinePageRestartLoad
) {
153 scoped_ptr
<OfflinePageMetadataStoreImpl
> store(BuildStore());
155 OfflinePageItem
offline_page(GURL(kTestURL
), kTestBookmarkId
,
156 base::FilePath(kFilePath
), kFileSize
);
157 store
->AddOfflinePage(
159 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback
,
160 base::Unretained(this), ADD
));
162 EXPECT_EQ(ADD
, last_called_callback_
);
163 EXPECT_EQ(STATUS_TRUE
, last_status_
);
165 // Reset the store first to ensure file lock is removed.
167 store
= BuildStore().Pass();
169 store
->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback
,
170 base::Unretained(this)));
173 EXPECT_EQ(LOAD
, last_called_callback_
);
174 EXPECT_EQ(STATUS_TRUE
, last_status_
);
175 EXPECT_EQ(1U, offline_pages_
.size());
176 EXPECT_EQ(offline_page
.url
, offline_pages_
[0].url
);
177 EXPECT_EQ(offline_page
.bookmark_id
, offline_pages_
[0].bookmark_id
);
178 EXPECT_EQ(offline_page
.version
, offline_pages_
[0].version
);
179 EXPECT_EQ(offline_page
.file_path
, offline_pages_
[0].file_path
);
180 EXPECT_EQ(offline_page
.file_size
, offline_pages_
[0].file_size
);
181 EXPECT_EQ(offline_page
.creation_time
, offline_pages_
[0].creation_time
);
182 EXPECT_EQ(offline_page
.last_access_time
, offline_pages_
[0].last_access_time
);
185 // Tests removing offline page metadata from the store, for which it first adds
186 // metadata of an offline page.
187 TEST_F(OfflinePageMetadataStoreImplTest
, RemoveOfflinePage
) {
188 scoped_ptr
<OfflinePageMetadataStoreImpl
> store(BuildStore());
190 OfflinePageItem
offline_page(GURL(kTestURL
), kTestBookmarkId
,
191 base::FilePath(kFilePath
), kFileSize
);
192 store
->AddOfflinePage(
194 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback
,
195 base::Unretained(this), ADD
));
196 store
->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback
,
197 base::Unretained(this)));
198 std::vector
<int64
> ids_to_remove
;
199 ids_to_remove
.push_back(offline_page
.bookmark_id
);
200 store
->RemoveOfflinePages(
202 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback
,
203 base::Unretained(this), REMOVE
));
204 store
->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback
,
205 base::Unretained(this)));
207 store
= BuildStore().Pass();
208 store
->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback
,
209 base::Unretained(this)));
210 // Add offline page is exectued:
212 EXPECT_EQ(ADD
, last_called_callback_
);
213 EXPECT_EQ(STATUS_TRUE
, last_status_
);
219 EXPECT_EQ(LOAD
, last_called_callback_
);
220 EXPECT_EQ(STATUS_TRUE
, last_status_
);
221 EXPECT_EQ(1U, offline_pages_
.size());
223 // Remove offline page is exectued:
226 EXPECT_EQ(REMOVE
, last_called_callback_
);
227 EXPECT_EQ(STATUS_TRUE
, last_status_
);
233 EXPECT_EQ(LOAD
, last_called_callback_
);
234 EXPECT_EQ(STATUS_TRUE
, last_status_
);
235 EXPECT_EQ(0U, offline_pages_
.size());
237 // Checking the value after reseting the store.
240 EXPECT_EQ(LOAD
, last_called_callback_
);
241 EXPECT_EQ(STATUS_TRUE
, last_status_
);
242 EXPECT_EQ(0U, offline_pages_
.size());
245 // Adds metadata of multiple offline pages into a store and removes some.
246 TEST_F(OfflinePageMetadataStoreImplTest
, AddRemoveMultipleOfflinePages
) {
247 scoped_ptr
<OfflinePageMetadataStoreImpl
> store(BuildStore());
249 OfflinePageItem
offline_page_1(GURL(kTestURL
), kTestBookmarkId
,
250 base::FilePath(kFilePath
), kFileSize
);
251 base::FilePath file_path_2
=
252 base::FilePath(FILE_PATH_LITERAL("//other.page.com.mhtml"));
253 OfflinePageItem
offline_page_2(GURL("https://other.page.com"), 5678LL,
254 file_path_2
, 12345, base::Time::Now());
255 store
->AddOfflinePage(
257 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback
,
258 base::Unretained(this), ADD
));
260 EXPECT_EQ(ADD
, last_called_callback_
);
261 EXPECT_EQ(STATUS_TRUE
, last_status_
);
264 store
->AddOfflinePage(
266 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback
,
267 base::Unretained(this), ADD
));
269 EXPECT_EQ(ADD
, last_called_callback_
);
270 EXPECT_EQ(STATUS_TRUE
, last_status_
);
273 store
->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback
,
274 base::Unretained(this)));
277 EXPECT_EQ(LOAD
, last_called_callback_
);
278 EXPECT_EQ(STATUS_TRUE
, last_status_
);
279 EXPECT_EQ(2U, offline_pages_
.size());
281 std::vector
<int64
> ids_to_remove
;
282 ids_to_remove
.push_back(offline_page_1
.bookmark_id
);
283 store
->RemoveOfflinePages(
285 base::Bind(&OfflinePageMetadataStoreImplTest::UpdateCallback
,
286 base::Unretained(this), REMOVE
));
288 EXPECT_EQ(REMOVE
, last_called_callback_
);
289 EXPECT_EQ(STATUS_TRUE
, last_status_
);
293 store
= BuildStore().Pass();
294 store
->Load(base::Bind(&OfflinePageMetadataStoreImplTest::LoadCallback
,
295 base::Unretained(this)));
298 EXPECT_EQ(LOAD
, last_called_callback_
);
299 EXPECT_EQ(STATUS_TRUE
, last_status_
);
300 EXPECT_EQ(1U, offline_pages_
.size());
301 EXPECT_EQ(offline_page_2
.url
, offline_pages_
[0].url
);
302 EXPECT_EQ(offline_page_2
.bookmark_id
, offline_pages_
[0].bookmark_id
);
303 EXPECT_EQ(offline_page_2
.version
, offline_pages_
[0].version
);
304 EXPECT_EQ(offline_page_2
.file_path
, offline_pages_
[0].file_path
);
305 EXPECT_EQ(offline_page_2
.file_size
, offline_pages_
[0].file_size
);
306 EXPECT_EQ(offline_page_2
.creation_time
, offline_pages_
[0].creation_time
);
307 EXPECT_EQ(offline_page_2
.last_access_time
,
308 offline_pages_
[0].last_access_time
);
313 } // namespace offline_pages