[Sync] Componentize UIModelWorker.
[chromium-blink-merge.git] / components / enhanced_bookmarks / image_store_unittest.cc
blob962b3fd0161a023a10fe740603b18b3bd6be9b1a
1 // Copyright 2014 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/enhanced_bookmarks/image_store.h"
7 #include "base/files/file_path.h"
8 #include "base/files/scoped_temp_dir.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "components/enhanced_bookmarks/image_record.h"
11 #include "components/enhanced_bookmarks/image_store_util.h"
12 #include "components/enhanced_bookmarks/persistent_image_store.h"
13 #include "components/enhanced_bookmarks/test_image_store.h"
14 #include "sql/statement.h"
15 #include "testing/platform_test.h"
16 #include "third_party/skia/include/core/SkBitmap.h"
17 #include "third_party/skia/include/core/SkColor.h"
18 #include "url/gurl.h"
20 namespace {
22 scoped_ptr<gfx::Image> CreateImage(
23 int width, int height, int a, int r, int g, int b) {
24 SkBitmap bitmap;
25 bitmap.allocN32Pixels(width, height);
26 bitmap.eraseARGB(a, r, g, b);
27 scoped_ptr<gfx::Image> image(
28 new gfx::Image(gfx::Image::CreateFrom1xBitmap(bitmap)));
30 #if defined(OS_IOS)
31 // Make sure the image has a kImageRepCocoaTouch.
32 image->ToUIImage();
33 #endif // defined(OS_IOS)
35 return image;
38 scoped_ptr<gfx::Image> GenerateWhiteImage() {
39 return CreateImage(42, 24, 255, 255, 255, 255);
42 scoped_ptr<gfx::Image> GenerateBlackImage(int width, int height) {
43 return CreateImage(width, height, 255, 0, 0, 0);
46 scoped_ptr<gfx::Image> GenerateBlackImage() {
47 return GenerateBlackImage(42, 24);
50 // Returns true if the two images are identical.
51 bool CompareImages(const gfx::Image& image_1, const gfx::Image& image_2) {
52 if (image_1.IsEmpty() && image_2.IsEmpty())
53 return true;
55 if (image_1.IsEmpty() || image_2.IsEmpty())
56 return false;
58 scoped_refptr<base::RefCountedMemory> image_1_bytes =
59 enhanced_bookmarks::BytesForImage(image_1);
60 scoped_refptr<base::RefCountedMemory> image_2_bytes =
61 enhanced_bookmarks::BytesForImage(image_2);
63 if (image_1_bytes->size() != image_2_bytes->size())
64 return false;
66 return !memcmp(image_1_bytes->front(),
67 image_2_bytes->front(),
68 image_1_bytes->size());
71 bool CreateV1PersistentImageStoreDB(const base::FilePath& path) {
72 sql::Connection db;
73 if (!db.Open(path))
74 return false;
76 if (db.DoesTableExist("images_by_url"))
77 return false;
79 const char kV1TableSql[] =
80 "CREATE TABLE IF NOT EXISTS images_by_url ("
81 "page_url LONGVARCHAR NOT NULL,"
82 "image_url LONGVARCHAR NOT NULL,"
83 "image_data BLOB,"
84 "width INTEGER,"
85 "height INTEGER"
86 ")";
87 if (!db.Execute(kV1TableSql))
88 return false;
90 const char kV1IndexSql[] =
91 "CREATE INDEX IF NOT EXISTS images_by_url_idx ON images_by_url(page_url)";
92 if (!db.Execute(kV1IndexSql))
93 return false;
95 sql::Statement statement(db.GetUniqueStatement(
96 "INSERT INTO images_by_url "
97 "(page_url, image_url, image_data, width, height) "
98 "VALUES (?, ?, ?, ?, ?)"));
99 statement.BindString(0, "foo://bar");
100 statement.BindString(1, "http://a.jpg");
101 scoped_refptr<base::RefCountedMemory> image_bytes =
102 enhanced_bookmarks::BytesForImage(*GenerateWhiteImage());
103 statement.BindBlob(2, image_bytes->front(), (int)image_bytes->size());
104 statement.BindInt(3, 42);
105 statement.BindInt(4, 24);
107 return statement.Run();
110 // Factory functions for creating instances of the implementations.
111 template <class T>
112 ImageStore* CreateStore(base::ScopedTempDir& folder);
114 template <>
115 ImageStore* CreateStore<TestImageStore>(
116 base::ScopedTempDir& folder) {
117 return new TestImageStore();
120 template <>
121 ImageStore* CreateStore<PersistentImageStore>(
122 base::ScopedTempDir& folder) {
123 return new PersistentImageStore(folder.path());
126 // Methods to check if persistence is on or not.
127 template <class T> bool ShouldPersist();
128 template <> bool ShouldPersist<TestImageStore>() { return false; }
129 template <> bool ShouldPersist<PersistentImageStore>() { return true; }
131 // Test fixture class template for the abstract API.
132 template <class T>
133 class ImageStoreUnitTest : public PlatformTest {
134 protected:
135 ImageStoreUnitTest() {}
136 ~ImageStoreUnitTest() override {}
138 void SetUp() override {
139 bool success = tempDir_.CreateUniqueTempDir();
140 ASSERT_TRUE(success);
141 store_.reset(CreateStore<T>(tempDir_));
144 void TearDown() override {
145 if (store_ && use_persistent_store())
146 store_->ClearAll();
149 bool use_persistent_store() const { return ShouldPersist<T>(); }
150 void ResetStore() { store_.reset(CreateStore<T>(tempDir_)); }
152 // The directory the database is saved into.
153 base::ScopedTempDir tempDir_;
154 // The object the fixture is testing, via its base interface.
155 scoped_ptr<ImageStore> store_;
157 private:
158 DISALLOW_COPY_AND_ASSIGN(ImageStoreUnitTest);
161 // The list of implementations of the abstract API that are going to be tested.
162 typedef testing::Types<TestImageStore,
163 PersistentImageStore> Implementations;
165 TYPED_TEST_CASE(ImageStoreUnitTest, Implementations);
167 // All those tests are run on all the implementations.
168 TYPED_TEST(ImageStoreUnitTest, StartsEmpty) {
169 std::set<GURL> all_urls;
170 this->store_->GetAllPageUrls(&all_urls);
171 EXPECT_EQ(0u, all_urls.size());
174 TYPED_TEST(ImageStoreUnitTest, StoreOne) {
175 scoped_refptr<enhanced_bookmarks::ImageRecord> image(
176 new enhanced_bookmarks::ImageRecord(
177 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK));
178 this->store_->Insert(GURL("foo://bar"), image);
180 std::set<GURL> all_urls;
181 this->store_->GetAllPageUrls(&all_urls);
182 EXPECT_EQ(1u, all_urls.size());
183 EXPECT_EQ(GURL("foo://bar"), *all_urls.begin());
184 EXPECT_TRUE(this->store_->HasKey(GURL("foo://bar")));
187 TYPED_TEST(ImageStoreUnitTest, Retrieve) {
188 const GURL url("foo://bar");
189 scoped_refptr<enhanced_bookmarks::ImageRecord> image_in(
190 new enhanced_bookmarks::ImageRecord(
191 CreateImage(42, 24, 1, 0, 0, 1), GURL("http://a.jpg"), SK_ColorBLUE));
192 this->store_->Insert(url, image_in);
194 scoped_refptr<enhanced_bookmarks::ImageRecord> image_out =
195 this->store_->Get(url);
196 const gfx::Size size = this->store_->GetSize(url);
198 EXPECT_EQ(42, size.width());
199 EXPECT_EQ(24, size.height());
200 EXPECT_EQ(image_in->url, image_out->url);
201 EXPECT_TRUE(CompareImages(*image_in->image, *image_out->image));
202 EXPECT_EQ(SK_ColorBLUE, image_out->dominant_color);
205 TYPED_TEST(ImageStoreUnitTest, Erase) {
206 const GURL url("foo://bar");
207 scoped_refptr<enhanced_bookmarks::ImageRecord> image(
208 new enhanced_bookmarks::ImageRecord(
209 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK));
210 this->store_->Insert(url, image);
211 this->store_->Erase(url);
213 EXPECT_FALSE(this->store_->HasKey(url));
214 std::set<GURL> all_urls;
215 this->store_->GetAllPageUrls(&all_urls);
216 EXPECT_EQ(0u, all_urls.size());
219 TYPED_TEST(ImageStoreUnitTest, ClearAll) {
220 const GURL url_foo("http://foo");
221 scoped_refptr<enhanced_bookmarks::ImageRecord> black_image(
222 new enhanced_bookmarks::ImageRecord(
223 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK));
224 this->store_->Insert(url_foo, black_image);
225 const GURL url_bar("http://bar");
226 scoped_refptr<enhanced_bookmarks::ImageRecord> white_image(
227 new enhanced_bookmarks::ImageRecord(
228 GenerateWhiteImage(), GURL("http://a.jpg"), SK_ColorWHITE));
229 this->store_->Insert(url_bar, white_image);
231 this->store_->ClearAll();
233 EXPECT_FALSE(this->store_->HasKey(url_foo));
234 EXPECT_FALSE(this->store_->HasKey(url_bar));
235 std::set<GURL> all_urls;
236 this->store_->GetAllPageUrls(&all_urls);
237 EXPECT_EQ(0u, all_urls.size());
240 TYPED_TEST(ImageStoreUnitTest, Update) {
241 const GURL url("foo://bar");
243 scoped_refptr<enhanced_bookmarks::ImageRecord> image1(
244 new enhanced_bookmarks::ImageRecord(
245 GenerateWhiteImage(), GURL("1.jpg"), SK_ColorWHITE));
246 this->store_->Insert(url, image1);
248 scoped_refptr<enhanced_bookmarks::ImageRecord> image2(
249 new enhanced_bookmarks::ImageRecord(
250 GenerateBlackImage(), GURL("2.jpg"), SK_ColorBLACK));
251 this->store_->Insert(url, image2);
253 scoped_refptr<enhanced_bookmarks::ImageRecord> image_out =
254 this->store_->Get(url);
256 EXPECT_TRUE(this->store_->HasKey(url));
257 std::set<GURL> all_urls;
258 this->store_->GetAllPageUrls(&all_urls);
259 EXPECT_EQ(1u, all_urls.size());
260 EXPECT_EQ(image2->url, image_out->url);
261 EXPECT_TRUE(CompareImages(*image2->image, *image_out->image));
262 EXPECT_EQ(SK_ColorBLACK, image_out->dominant_color);
265 TYPED_TEST(ImageStoreUnitTest, Persistence) {
266 const GURL url("foo://bar");
267 scoped_refptr<enhanced_bookmarks::ImageRecord> image_in(
268 new enhanced_bookmarks::ImageRecord(
269 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK));
270 this->store_->Insert(url, image_in);
272 this->ResetStore();
273 if (this->use_persistent_store()) {
274 std::set<GURL> all_urls;
275 this->store_->GetAllPageUrls(&all_urls);
276 EXPECT_EQ(1u, all_urls.size());
277 EXPECT_EQ(url, *all_urls.begin());
278 EXPECT_TRUE(this->store_->HasKey(url));
279 scoped_refptr<enhanced_bookmarks::ImageRecord> image_out =
280 this->store_->Get(url);
282 EXPECT_EQ(image_in->url, image_out->url);
283 EXPECT_TRUE(CompareImages(*image_in->image, *image_out->image));
284 EXPECT_EQ(image_in->dominant_color, image_out->dominant_color);
285 } else {
286 std::set<GURL> all_urls;
287 this->store_->GetAllPageUrls(&all_urls);
288 EXPECT_EQ(0u, all_urls.size());
289 EXPECT_FALSE(this->store_->HasKey(url));
293 TYPED_TEST(ImageStoreUnitTest, MigrationToV2) {
294 // Migration is available only with persistent stores.
295 if (!this->use_persistent_store())
296 return;
298 // Set up v1 DB.
299 EXPECT_TRUE(CreateV1PersistentImageStoreDB(this->tempDir_.path().Append(
300 base::FilePath::FromUTF8Unsafe("BookmarkImageAndUrlStore.db"))));
302 scoped_refptr<enhanced_bookmarks::ImageRecord> image_out =
303 this->store_->Get(GURL("foo://bar"));
304 EXPECT_EQ(SK_ColorWHITE, image_out->dominant_color);
307 TYPED_TEST(ImageStoreUnitTest, GetSize) {
308 const GURL url("foo://bar");
309 scoped_refptr<enhanced_bookmarks::ImageRecord> image_in(
310 new enhanced_bookmarks::ImageRecord(
311 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK));
313 int64 size = 0;
314 if (this->use_persistent_store()) {
315 // File shouldn't exist before we actually start using it since we do lazy
316 // initialization.
317 EXPECT_EQ(this->store_->GetStoreSizeInBytes(), -1);
318 } else {
319 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 1024);
321 for (int i = 0; i < 100; ++i) {
322 this->store_->Insert(GURL(url.spec() + '/' + base::IntToString(i)),
323 image_in);
324 EXPECT_GE(this->store_->GetStoreSizeInBytes(), size);
325 size = this->store_->GetStoreSizeInBytes();
328 if (this->use_persistent_store()) {
329 EXPECT_GE(this->store_->GetStoreSizeInBytes(), 80 * 1024); // 80kb
330 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 200 * 1024); // 200kb
331 } else {
332 EXPECT_GE(this->store_->GetStoreSizeInBytes(), 400 * 1024); // 400kb
333 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 500 * 1024); // 500kb
337 } // namespace