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/scoped_temp_dir.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "components/enhanced_bookmarks/image_store_util.h"
10 #include "components/enhanced_bookmarks/persistent_image_store.h"
11 #include "components/enhanced_bookmarks/test_image_store.h"
12 #include "testing/platform_test.h"
13 #include "third_party/skia/include/core/SkBitmap.h"
18 gfx::Image CreateImage(int width, int height, int a, int r, int g, int b) {
20 bitmap.allocN32Pixels(width, height);
21 bitmap.eraseARGB(a, r, g, b);
22 gfx::Image image(gfx::Image::CreateFrom1xBitmap(bitmap));
25 // Make sure the image has a kImageRepCocoaTouch.
27 #endif // defined(OS_IOS)
32 gfx::Image GenerateWhiteImage() {
33 return CreateImage(42, 24, 255, 255, 255, 255);
36 gfx::Image GenerateBlackImage(int width, int height) {
37 return CreateImage(width, height, 255, 0, 0, 0);
40 gfx::Image GenerateBlackImage() {
41 return GenerateBlackImage(42, 24);
44 // Returns true if the two images are identical.
45 bool CompareImages(const gfx::Image& image_1, const gfx::Image& image_2) {
46 if (image_1.IsEmpty() && image_2.IsEmpty())
49 if (image_1.IsEmpty() || image_2.IsEmpty())
52 scoped_refptr<base::RefCountedMemory> image_1_bytes =
53 enhanced_bookmarks::BytesForImage(image_1);
54 scoped_refptr<base::RefCountedMemory> image_2_bytes =
55 enhanced_bookmarks::BytesForImage(image_2);
57 if (image_1_bytes->size() != image_2_bytes->size())
60 return !memcmp(image_1_bytes->front(),
61 image_2_bytes->front(),
62 image_1_bytes->size());
65 // Factory functions for creating instances of the implementations.
67 ImageStore* CreateStore(base::ScopedTempDir& folder);
70 ImageStore* CreateStore<TestImageStore>(
71 base::ScopedTempDir& folder) {
72 return new TestImageStore();
76 ImageStore* CreateStore<PersistentImageStore>(
77 base::ScopedTempDir& folder) {
78 return new PersistentImageStore(folder.path());
81 // Methods to check if persistence is on or not.
82 template <class T> bool ShouldPersist();
83 template <> bool ShouldPersist<TestImageStore>() { return false; }
84 template <> bool ShouldPersist<PersistentImageStore>() { return true; }
86 // Test fixture class template for the abstract API.
88 class ImageStoreUnitTest : public PlatformTest {
90 ImageStoreUnitTest() {}
91 virtual ~ImageStoreUnitTest() {}
93 virtual void SetUp() override {
94 bool success = tempDir_.CreateUniqueTempDir();
96 store_.reset(CreateStore<T>(tempDir_));
99 virtual void TearDown() override {
100 if (store_ && use_persistent_store())
104 bool use_persistent_store() const { return ShouldPersist<T>(); }
105 void ResetStore() { store_.reset(CreateStore<T>(tempDir_)); }
107 // The directory the database is saved into.
108 base::ScopedTempDir tempDir_;
109 // The object the fixture is testing, via its base interface.
110 scoped_ptr<ImageStore> store_;
113 DISALLOW_COPY_AND_ASSIGN(ImageStoreUnitTest);
116 // The list of implementations of the abstract API that are going to be tested.
117 typedef testing::Types<TestImageStore,
118 PersistentImageStore> Implementations;
120 TYPED_TEST_CASE(ImageStoreUnitTest, Implementations);
122 // All those tests are run on all the implementations.
123 TYPED_TEST(ImageStoreUnitTest, StartsEmpty) {
124 std::set<GURL> all_urls;
125 this->store_->GetAllPageUrls(&all_urls);
126 EXPECT_EQ(0u, all_urls.size());
129 TYPED_TEST(ImageStoreUnitTest, StoreOne) {
130 this->store_->Insert(GURL("foo://bar"), GURL("a.jpg"), GenerateBlackImage());
132 std::set<GURL> all_urls;
133 this->store_->GetAllPageUrls(&all_urls);
134 EXPECT_EQ(1u, all_urls.size());
135 EXPECT_EQ(GURL("foo://bar"), *all_urls.begin());
136 EXPECT_TRUE(this->store_->HasKey(GURL("foo://bar")));
139 TYPED_TEST(ImageStoreUnitTest, Retrieve) {
140 gfx::Image src_image = GenerateBlackImage(42, 24);
141 const GURL url("foo://bar");
142 const GURL image_url("a.jpg");
143 this->store_->Insert(url, image_url, src_image);
145 std::pair<gfx::Image, GURL> image_info = this->store_->Get(url);
146 gfx::Size size = this->store_->GetSize(url);
148 EXPECT_EQ(size.width(), 42);
149 EXPECT_EQ(size.height(), 24);
150 EXPECT_EQ(image_url, image_info.second);
151 EXPECT_TRUE(CompareImages(src_image, image_info.first));
154 TYPED_TEST(ImageStoreUnitTest, Erase) {
155 gfx::Image src_image = GenerateBlackImage();
156 const GURL url("foo://bar");
157 const GURL image_url("a.jpg");
158 this->store_->Insert(url, image_url, src_image);
159 this->store_->Erase(url);
161 EXPECT_FALSE(this->store_->HasKey(url));
162 std::set<GURL> all_urls;
163 this->store_->GetAllPageUrls(&all_urls);
164 EXPECT_EQ(0u, all_urls.size());
167 TYPED_TEST(ImageStoreUnitTest, ClearAll) {
168 const GURL url_foo("http://foo");
169 this->store_->Insert(url_foo, GURL("foo.jpg"), GenerateBlackImage());
170 const GURL url_bar("http://bar");
171 this->store_->Insert(url_foo, GURL("bar.jpg"), GenerateWhiteImage());
173 this->store_->ClearAll();
175 EXPECT_FALSE(this->store_->HasKey(url_foo));
176 EXPECT_FALSE(this->store_->HasKey(url_bar));
177 std::set<GURL> all_urls;
178 this->store_->GetAllPageUrls(&all_urls);
179 EXPECT_EQ(0u, all_urls.size());
182 TYPED_TEST(ImageStoreUnitTest, Update) {
183 gfx::Image src_image1 = GenerateWhiteImage();
184 gfx::Image src_image2 = GenerateBlackImage();
185 const GURL url("foo://bar");
186 const GURL image_url1("1.jpg");
187 this->store_->Insert(url, image_url1, src_image1);
189 const GURL image_url2("2.jpg");
190 this->store_->Insert(url, image_url2, src_image2);
192 std::pair<gfx::Image, GURL> image_info = this->store_->Get(url);
194 EXPECT_TRUE(this->store_->HasKey(url));
195 std::set<GURL> all_urls;
196 this->store_->GetAllPageUrls(&all_urls);
197 EXPECT_EQ(1u, all_urls.size());
198 EXPECT_EQ(image_url2, image_info.second);
199 EXPECT_TRUE(CompareImages(src_image2, image_info.first));
202 TYPED_TEST(ImageStoreUnitTest, Persistence) {
203 gfx::Image src_image = GenerateBlackImage();
204 const GURL url("foo://bar");
205 const GURL image_url("a.jpg");
206 this->store_->Insert(url, image_url, src_image);
209 if (this->use_persistent_store()) {
210 std::set<GURL> all_urls;
211 this->store_->GetAllPageUrls(&all_urls);
212 EXPECT_EQ(1u, all_urls.size());
213 EXPECT_EQ(GURL("foo://bar"), *all_urls.begin());
214 EXPECT_TRUE(this->store_->HasKey(GURL("foo://bar")));
215 std::pair<gfx::Image, GURL> image_info = this->store_->Get(url);
217 EXPECT_EQ(image_url, image_info.second);
218 EXPECT_TRUE(CompareImages(src_image, image_info.first));
220 std::set<GURL> all_urls;
221 this->store_->GetAllPageUrls(&all_urls);
222 EXPECT_EQ(0u, all_urls.size());
223 EXPECT_FALSE(this->store_->HasKey(GURL("foo://bar")));
227 TYPED_TEST(ImageStoreUnitTest, GetSize) {
228 gfx::Image src_image = GenerateBlackImage();
229 const GURL url("foo://bar");
230 const GURL image_url("a.jpg");
233 if (this->use_persistent_store()) {
234 // File shouldn't exist before we actually start using it since we do lazy
236 EXPECT_EQ(this->store_->GetStoreSizeInBytes(), -1);
238 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 1024);
240 for (int i = 0; i < 100; ++i) {
241 this->store_->Insert(
242 GURL(url.spec() + '/' + base::IntToString(i)), image_url, src_image);
243 EXPECT_GE(this->store_->GetStoreSizeInBytes(), size);
244 size = this->store_->GetStoreSizeInBytes();
247 if (this->use_persistent_store()) {
248 EXPECT_GE(this->store_->GetStoreSizeInBytes(), 90 * 1024); // 90kb
249 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 200 * 1024); // 200kb
251 EXPECT_GE(this->store_->GetStoreSizeInBytes(), 400 * 1024); // 400kb
252 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 500 * 1024); // 500kb