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(), 80 * 1024); // 80kb
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