OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/enhanced_bookmarks/image_store.h" | 5 #include "components/enhanced_bookmarks/image_store.h" |
6 | 6 |
| 7 #include "base/files/file_path.h" |
7 #include "base/files/scoped_temp_dir.h" | 8 #include "base/files/scoped_temp_dir.h" |
8 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "components/enhanced_bookmarks/image_record.h" |
9 #include "components/enhanced_bookmarks/image_store_util.h" | 11 #include "components/enhanced_bookmarks/image_store_util.h" |
10 #include "components/enhanced_bookmarks/persistent_image_store.h" | 12 #include "components/enhanced_bookmarks/persistent_image_store.h" |
11 #include "components/enhanced_bookmarks/test_image_store.h" | 13 #include "components/enhanced_bookmarks/test_image_store.h" |
| 14 #include "sql/statement.h" |
12 #include "testing/platform_test.h" | 15 #include "testing/platform_test.h" |
13 #include "third_party/skia/include/core/SkBitmap.h" | 16 #include "third_party/skia/include/core/SkBitmap.h" |
| 17 #include "third_party/skia/include/core/SkColor.h" |
14 #include "url/gurl.h" | 18 #include "url/gurl.h" |
15 | 19 |
16 namespace { | 20 namespace { |
17 | 21 |
18 gfx::Image CreateImage(int width, int height, int a, int r, int g, int b) { | 22 gfx::Image CreateImage(int width, int height, int a, int r, int g, int b) { |
19 SkBitmap bitmap; | 23 SkBitmap bitmap; |
20 bitmap.allocN32Pixels(width, height); | 24 bitmap.allocN32Pixels(width, height); |
21 bitmap.eraseARGB(a, r, g, b); | 25 bitmap.eraseARGB(a, r, g, b); |
22 gfx::Image image(gfx::Image::CreateFrom1xBitmap(bitmap)); | 26 gfx::Image image(gfx::Image::CreateFrom1xBitmap(bitmap)); |
23 | 27 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 enhanced_bookmarks::BytesForImage(image_2); | 59 enhanced_bookmarks::BytesForImage(image_2); |
56 | 60 |
57 if (image_1_bytes->size() != image_2_bytes->size()) | 61 if (image_1_bytes->size() != image_2_bytes->size()) |
58 return false; | 62 return false; |
59 | 63 |
60 return !memcmp(image_1_bytes->front(), | 64 return !memcmp(image_1_bytes->front(), |
61 image_2_bytes->front(), | 65 image_2_bytes->front(), |
62 image_1_bytes->size()); | 66 image_1_bytes->size()); |
63 } | 67 } |
64 | 68 |
| 69 bool CreateV1PersistentImageStoreDB(const base::FilePath& path) { |
| 70 sql::Connection db; |
| 71 if (!db.Open(path)) |
| 72 return false; |
| 73 |
| 74 if (db.DoesTableExist("images_by_url")) |
| 75 return false; |
| 76 |
| 77 const char kV1TableSql[] = |
| 78 "CREATE TABLE IF NOT EXISTS images_by_url (" |
| 79 "page_url LONGVARCHAR NOT NULL," |
| 80 "image_url LONGVARCHAR NOT NULL," |
| 81 "image_data BLOB," |
| 82 "width INTEGER," |
| 83 "height INTEGER" |
| 84 ")"; |
| 85 if (!db.Execute(kV1TableSql)) |
| 86 return false; |
| 87 |
| 88 const char kV1IndexSql[] = |
| 89 "CREATE INDEX IF NOT EXISTS images_by_url_idx ON images_by_url(page_url)"; |
| 90 if (!db.Execute(kV1IndexSql)) |
| 91 return false; |
| 92 |
| 93 sql::Statement statement(db.GetUniqueStatement( |
| 94 "INSERT INTO images_by_url " |
| 95 "(page_url, image_url, image_data, width, height) " |
| 96 "VALUES (?, ?, ?, ?, ?)")); |
| 97 statement.BindString(0, "foo://bar"); |
| 98 statement.BindString(1, "http://a.jpg"); |
| 99 scoped_refptr<base::RefCountedMemory> image_bytes = |
| 100 enhanced_bookmarks::BytesForImage(GenerateWhiteImage()); |
| 101 statement.BindBlob(2, image_bytes->front(), (int)image_bytes->size()); |
| 102 statement.BindInt(3, 42); |
| 103 statement.BindInt(4, 24); |
| 104 |
| 105 return statement.Run(); |
| 106 } |
| 107 |
65 // Factory functions for creating instances of the implementations. | 108 // Factory functions for creating instances of the implementations. |
66 template <class T> | 109 template <class T> |
67 ImageStore* CreateStore(base::ScopedTempDir& folder); | 110 ImageStore* CreateStore(base::ScopedTempDir& folder); |
68 | 111 |
69 template <> | 112 template <> |
70 ImageStore* CreateStore<TestImageStore>( | 113 ImageStore* CreateStore<TestImageStore>( |
71 base::ScopedTempDir& folder) { | 114 base::ScopedTempDir& folder) { |
72 return new TestImageStore(); | 115 return new TestImageStore(); |
73 } | 116 } |
74 | 117 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
120 TYPED_TEST_CASE(ImageStoreUnitTest, Implementations); | 163 TYPED_TEST_CASE(ImageStoreUnitTest, Implementations); |
121 | 164 |
122 // All those tests are run on all the implementations. | 165 // All those tests are run on all the implementations. |
123 TYPED_TEST(ImageStoreUnitTest, StartsEmpty) { | 166 TYPED_TEST(ImageStoreUnitTest, StartsEmpty) { |
124 std::set<GURL> all_urls; | 167 std::set<GURL> all_urls; |
125 this->store_->GetAllPageUrls(&all_urls); | 168 this->store_->GetAllPageUrls(&all_urls); |
126 EXPECT_EQ(0u, all_urls.size()); | 169 EXPECT_EQ(0u, all_urls.size()); |
127 } | 170 } |
128 | 171 |
129 TYPED_TEST(ImageStoreUnitTest, StoreOne) { | 172 TYPED_TEST(ImageStoreUnitTest, StoreOne) { |
130 this->store_->Insert(GURL("foo://bar"), GURL("a.jpg"), GenerateBlackImage()); | 173 const enhanced_bookmarks::ImageRecord image( |
| 174 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); |
| 175 this->store_->Insert(GURL("foo://bar"), image); |
131 | 176 |
132 std::set<GURL> all_urls; | 177 std::set<GURL> all_urls; |
133 this->store_->GetAllPageUrls(&all_urls); | 178 this->store_->GetAllPageUrls(&all_urls); |
134 EXPECT_EQ(1u, all_urls.size()); | 179 EXPECT_EQ(1u, all_urls.size()); |
135 EXPECT_EQ(GURL("foo://bar"), *all_urls.begin()); | 180 EXPECT_EQ(GURL("foo://bar"), *all_urls.begin()); |
136 EXPECT_TRUE(this->store_->HasKey(GURL("foo://bar"))); | 181 EXPECT_TRUE(this->store_->HasKey(GURL("foo://bar"))); |
137 } | 182 } |
138 | 183 |
139 TYPED_TEST(ImageStoreUnitTest, Retrieve) { | 184 TYPED_TEST(ImageStoreUnitTest, Retrieve) { |
140 gfx::Image src_image = GenerateBlackImage(42, 24); | |
141 const GURL url("foo://bar"); | 185 const GURL url("foo://bar"); |
142 const GURL image_url("a.jpg"); | 186 const enhanced_bookmarks::ImageRecord image_in( |
143 this->store_->Insert(url, image_url, src_image); | 187 CreateImage(42, 24, 1, 0, 0, 1), GURL("http://a.jpg"), SK_ColorBLUE); |
| 188 this->store_->Insert(url, image_in); |
144 | 189 |
145 std::pair<gfx::Image, GURL> image_info = this->store_->Get(url); | 190 const enhanced_bookmarks::ImageRecord image_out = this->store_->Get(url); |
146 gfx::Size size = this->store_->GetSize(url); | 191 const gfx::Size size = this->store_->GetSize(url); |
147 | 192 |
148 EXPECT_EQ(size.width(), 42); | 193 EXPECT_EQ(42, size.width()); |
149 EXPECT_EQ(size.height(), 24); | 194 EXPECT_EQ(24, size.height()); |
150 EXPECT_EQ(image_url, image_info.second); | 195 EXPECT_EQ(image_in.url, image_out.url); |
151 EXPECT_TRUE(CompareImages(src_image, image_info.first)); | 196 EXPECT_TRUE(CompareImages(image_in.image, image_out.image)); |
| 197 EXPECT_EQ(SK_ColorBLUE, image_out.dominant_color); |
152 } | 198 } |
153 | 199 |
154 TYPED_TEST(ImageStoreUnitTest, Erase) { | 200 TYPED_TEST(ImageStoreUnitTest, Erase) { |
155 gfx::Image src_image = GenerateBlackImage(); | |
156 const GURL url("foo://bar"); | 201 const GURL url("foo://bar"); |
157 const GURL image_url("a.jpg"); | 202 const enhanced_bookmarks::ImageRecord image( |
158 this->store_->Insert(url, image_url, src_image); | 203 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); |
| 204 this->store_->Insert(url, image); |
159 this->store_->Erase(url); | 205 this->store_->Erase(url); |
160 | 206 |
161 EXPECT_FALSE(this->store_->HasKey(url)); | 207 EXPECT_FALSE(this->store_->HasKey(url)); |
162 std::set<GURL> all_urls; | 208 std::set<GURL> all_urls; |
163 this->store_->GetAllPageUrls(&all_urls); | 209 this->store_->GetAllPageUrls(&all_urls); |
164 EXPECT_EQ(0u, all_urls.size()); | 210 EXPECT_EQ(0u, all_urls.size()); |
165 } | 211 } |
166 | 212 |
167 TYPED_TEST(ImageStoreUnitTest, ClearAll) { | 213 TYPED_TEST(ImageStoreUnitTest, ClearAll) { |
168 const GURL url_foo("http://foo"); | 214 const GURL url_foo("http://foo"); |
169 this->store_->Insert(url_foo, GURL("foo.jpg"), GenerateBlackImage()); | 215 const enhanced_bookmarks::ImageRecord black_image( |
| 216 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); |
| 217 this->store_->Insert(url_foo, black_image); |
170 const GURL url_bar("http://bar"); | 218 const GURL url_bar("http://bar"); |
171 this->store_->Insert(url_foo, GURL("bar.jpg"), GenerateWhiteImage()); | 219 const enhanced_bookmarks::ImageRecord white_image( |
| 220 GenerateWhiteImage(), GURL("http://a.jpg"), SK_ColorWHITE); |
| 221 this->store_->Insert(url_bar, white_image); |
172 | 222 |
173 this->store_->ClearAll(); | 223 this->store_->ClearAll(); |
174 | 224 |
175 EXPECT_FALSE(this->store_->HasKey(url_foo)); | 225 EXPECT_FALSE(this->store_->HasKey(url_foo)); |
176 EXPECT_FALSE(this->store_->HasKey(url_bar)); | 226 EXPECT_FALSE(this->store_->HasKey(url_bar)); |
177 std::set<GURL> all_urls; | 227 std::set<GURL> all_urls; |
178 this->store_->GetAllPageUrls(&all_urls); | 228 this->store_->GetAllPageUrls(&all_urls); |
179 EXPECT_EQ(0u, all_urls.size()); | 229 EXPECT_EQ(0u, all_urls.size()); |
180 } | 230 } |
181 | 231 |
182 TYPED_TEST(ImageStoreUnitTest, Update) { | 232 TYPED_TEST(ImageStoreUnitTest, Update) { |
183 gfx::Image src_image1 = GenerateWhiteImage(); | |
184 gfx::Image src_image2 = GenerateBlackImage(); | |
185 const GURL url("foo://bar"); | 233 const GURL url("foo://bar"); |
186 const GURL image_url1("1.jpg"); | 234 const enhanced_bookmarks::ImageRecord image1(GenerateWhiteImage(), |
187 this->store_->Insert(url, image_url1, src_image1); | 235 GURL("1.jpg"), SK_ColorWHITE); |
| 236 this->store_->Insert(url, image1); |
188 | 237 |
189 const GURL image_url2("2.jpg"); | 238 const enhanced_bookmarks::ImageRecord image2(GenerateBlackImage(), |
190 this->store_->Insert(url, image_url2, src_image2); | 239 GURL("2.jpg"), SK_ColorBLACK); |
| 240 this->store_->Insert(url, image2); |
191 | 241 |
192 std::pair<gfx::Image, GURL> image_info = this->store_->Get(url); | 242 const enhanced_bookmarks::ImageRecord image_out = this->store_->Get(url); |
193 | 243 |
194 EXPECT_TRUE(this->store_->HasKey(url)); | 244 EXPECT_TRUE(this->store_->HasKey(url)); |
195 std::set<GURL> all_urls; | 245 std::set<GURL> all_urls; |
196 this->store_->GetAllPageUrls(&all_urls); | 246 this->store_->GetAllPageUrls(&all_urls); |
197 EXPECT_EQ(1u, all_urls.size()); | 247 EXPECT_EQ(1u, all_urls.size()); |
198 EXPECT_EQ(image_url2, image_info.second); | 248 EXPECT_EQ(image2.url, image_out.url); |
199 EXPECT_TRUE(CompareImages(src_image2, image_info.first)); | 249 EXPECT_TRUE(CompareImages(image2.image, image_out.image)); |
| 250 EXPECT_EQ(SK_ColorBLACK, image_out.dominant_color); |
200 } | 251 } |
201 | 252 |
202 TYPED_TEST(ImageStoreUnitTest, Persistence) { | 253 TYPED_TEST(ImageStoreUnitTest, Persistence) { |
203 gfx::Image src_image = GenerateBlackImage(); | |
204 const GURL url("foo://bar"); | 254 const GURL url("foo://bar"); |
205 const GURL image_url("a.jpg"); | 255 const enhanced_bookmarks::ImageRecord image_in( |
206 this->store_->Insert(url, image_url, src_image); | 256 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); |
| 257 this->store_->Insert(url, image_in); |
207 | 258 |
208 this->ResetStore(); | 259 this->ResetStore(); |
209 if (this->use_persistent_store()) { | 260 if (this->use_persistent_store()) { |
210 std::set<GURL> all_urls; | 261 std::set<GURL> all_urls; |
211 this->store_->GetAllPageUrls(&all_urls); | 262 this->store_->GetAllPageUrls(&all_urls); |
212 EXPECT_EQ(1u, all_urls.size()); | 263 EXPECT_EQ(1u, all_urls.size()); |
213 EXPECT_EQ(GURL("foo://bar"), *all_urls.begin()); | 264 EXPECT_EQ(url, *all_urls.begin()); |
214 EXPECT_TRUE(this->store_->HasKey(GURL("foo://bar"))); | 265 EXPECT_TRUE(this->store_->HasKey(url)); |
215 std::pair<gfx::Image, GURL> image_info = this->store_->Get(url); | 266 const enhanced_bookmarks::ImageRecord image_out = this->store_->Get(url); |
216 | 267 |
217 EXPECT_EQ(image_url, image_info.second); | 268 EXPECT_EQ(image_in.url, image_out.url); |
218 EXPECT_TRUE(CompareImages(src_image, image_info.first)); | 269 EXPECT_TRUE(CompareImages(image_in.image, image_out.image)); |
| 270 EXPECT_EQ(image_in.dominant_color, image_out.dominant_color); |
219 } else { | 271 } else { |
220 std::set<GURL> all_urls; | 272 std::set<GURL> all_urls; |
221 this->store_->GetAllPageUrls(&all_urls); | 273 this->store_->GetAllPageUrls(&all_urls); |
222 EXPECT_EQ(0u, all_urls.size()); | 274 EXPECT_EQ(0u, all_urls.size()); |
223 EXPECT_FALSE(this->store_->HasKey(GURL("foo://bar"))); | 275 EXPECT_FALSE(this->store_->HasKey(url)); |
224 } | 276 } |
225 } | 277 } |
226 | 278 |
| 279 TYPED_TEST(ImageStoreUnitTest, MigrationToV2) { |
| 280 // Migration is available only with persistent stores. |
| 281 if (!this->use_persistent_store()) |
| 282 return; |
| 283 |
| 284 // Set up v1 DB. |
| 285 EXPECT_TRUE(CreateV1PersistentImageStoreDB(this->tempDir_.path().Append( |
| 286 base::FilePath::FromUTF8Unsafe("BookmarkImageAndUrlStore.db")))); |
| 287 |
| 288 const enhanced_bookmarks::ImageRecord image_out = |
| 289 this->store_->Get(GURL("foo://bar")); |
| 290 EXPECT_EQ(SK_ColorWHITE, image_out.dominant_color); |
| 291 } |
| 292 |
227 TYPED_TEST(ImageStoreUnitTest, GetSize) { | 293 TYPED_TEST(ImageStoreUnitTest, GetSize) { |
228 gfx::Image src_image = GenerateBlackImage(); | |
229 const GURL url("foo://bar"); | 294 const GURL url("foo://bar"); |
230 const GURL image_url("a.jpg"); | 295 const enhanced_bookmarks::ImageRecord image_in( |
| 296 GenerateBlackImage(), GURL("http://a.jpg"), SK_ColorBLACK); |
231 | 297 |
232 int64 size = 0; | 298 int64 size = 0; |
233 if (this->use_persistent_store()) { | 299 if (this->use_persistent_store()) { |
234 // File shouldn't exist before we actually start using it since we do lazy | 300 // File shouldn't exist before we actually start using it since we do lazy |
235 // initialization. | 301 // initialization. |
236 EXPECT_EQ(this->store_->GetStoreSizeInBytes(), -1); | 302 EXPECT_EQ(this->store_->GetStoreSizeInBytes(), -1); |
237 } else { | 303 } else { |
238 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 1024); | 304 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 1024); |
239 } | 305 } |
240 for (int i = 0; i < 100; ++i) { | 306 for (int i = 0; i < 100; ++i) { |
241 this->store_->Insert( | 307 this->store_->Insert(GURL(url.spec() + '/' + base::IntToString(i)), |
242 GURL(url.spec() + '/' + base::IntToString(i)), image_url, src_image); | 308 image_in); |
243 EXPECT_GE(this->store_->GetStoreSizeInBytes(), size); | 309 EXPECT_GE(this->store_->GetStoreSizeInBytes(), size); |
244 size = this->store_->GetStoreSizeInBytes(); | 310 size = this->store_->GetStoreSizeInBytes(); |
245 } | 311 } |
246 | 312 |
247 if (this->use_persistent_store()) { | 313 if (this->use_persistent_store()) { |
248 EXPECT_GE(this->store_->GetStoreSizeInBytes(), 80 * 1024); // 80kb | 314 EXPECT_GE(this->store_->GetStoreSizeInBytes(), 80 * 1024); // 80kb |
249 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 200 * 1024); // 200kb | 315 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 200 * 1024); // 200kb |
250 } else { | 316 } else { |
251 EXPECT_GE(this->store_->GetStoreSizeInBytes(), 400 * 1024); // 400kb | 317 EXPECT_GE(this->store_->GetStoreSizeInBytes(), 400 * 1024); // 400kb |
252 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 500 * 1024); // 500kb | 318 EXPECT_LE(this->store_->GetStoreSizeInBytes(), 500 * 1024); // 500kb |
253 } | 319 } |
254 } | 320 } |
255 | 321 |
256 } // namespace | 322 } // namespace |
OLD | NEW |