Home | History | Annotate | Download | only in enhanced_bookmarks
      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.
      4 
      5 #include "components/enhanced_bookmarks/image_store.h"
      6 
      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"
     14 #include "url/gurl.h"
     15 
     16 namespace {
     17 
     18 gfx::Image CreateImage(int width, int height, int a, int r, int g, int b) {
     19   SkBitmap bitmap;
     20   bitmap.allocN32Pixels(width, height);
     21   bitmap.eraseARGB(a, r, g, b);
     22   gfx::Image image(gfx::Image::CreateFrom1xBitmap(bitmap));
     23 
     24 #if defined(OS_IOS)
     25   // Make sure the image has a kImageRepCocoaTouch.
     26   image.ToUIImage();
     27 #endif  // defined(OS_IOS)
     28 
     29   return image;
     30 }
     31 
     32 gfx::Image GenerateWhiteImage() {
     33   return CreateImage(42, 24, 255, 255, 255, 255);
     34 }
     35 
     36 gfx::Image GenerateBlackImage(int width, int height) {
     37   return CreateImage(width, height, 255, 0, 0, 0);
     38 }
     39 
     40 gfx::Image GenerateBlackImage() {
     41   return GenerateBlackImage(42, 24);
     42 }
     43 
     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())
     47     return true;
     48 
     49   if (image_1.IsEmpty() || image_2.IsEmpty())
     50     return false;
     51 
     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);
     56 
     57   if (image_1_bytes->size() != image_2_bytes->size())
     58     return false;
     59 
     60   return !memcmp(image_1_bytes->front(),
     61                  image_2_bytes->front(),
     62                  image_1_bytes->size());
     63 }
     64 
     65 // Factory functions for creating instances of the implementations.
     66 template <class T>
     67 ImageStore* CreateStore(base::ScopedTempDir& folder);
     68 
     69 template <>
     70 ImageStore* CreateStore<TestImageStore>(
     71     base::ScopedTempDir& folder) {
     72   return new TestImageStore();
     73 }
     74 
     75 template <>
     76 ImageStore* CreateStore<PersistentImageStore>(
     77     base::ScopedTempDir& folder) {
     78   return new PersistentImageStore(folder.path());
     79 }
     80 
     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; }
     85 
     86 // Test fixture class template for the abstract API.
     87 template <class T>
     88 class ImageStoreUnitTest : public PlatformTest {
     89  protected:
     90   ImageStoreUnitTest() {}
     91   virtual ~ImageStoreUnitTest() {}
     92 
     93   virtual void SetUp() OVERRIDE {
     94     bool success = tempDir_.CreateUniqueTempDir();
     95     ASSERT_TRUE(success);
     96     store_.reset(CreateStore<T>(tempDir_));
     97   }
     98 
     99   virtual void TearDown() OVERRIDE {
    100     if (store_ && use_persistent_store())
    101       store_->ClearAll();
    102   }
    103 
    104   bool use_persistent_store() const { return ShouldPersist<T>(); }
    105   void ResetStore() { store_.reset(CreateStore<T>(tempDir_)); }
    106 
    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_;
    111 
    112  private:
    113   DISALLOW_COPY_AND_ASSIGN(ImageStoreUnitTest);
    114 };
    115 
    116 // The list of implementations of the abstract API that are going to be tested.
    117 typedef testing::Types<TestImageStore,
    118                        PersistentImageStore> Implementations;
    119 
    120 TYPED_TEST_CASE(ImageStoreUnitTest, Implementations);
    121 
    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());
    127 }
    128 
    129 TYPED_TEST(ImageStoreUnitTest, StoreOne) {
    130   this->store_->Insert(GURL("foo://bar"), GURL("a.jpg"), GenerateBlackImage());
    131 
    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")));
    137 }
    138 
    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);
    144 
    145   std::pair<gfx::Image, GURL> image_info = this->store_->Get(url);
    146   gfx::Size size = this->store_->GetSize(url);
    147 
    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));
    152 }
    153 
    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);
    160 
    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());
    165 }
    166 
    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());
    172 
    173   this->store_->ClearAll();
    174 
    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());
    180 }
    181 
    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);
    188 
    189   const GURL image_url2("2.jpg");
    190   this->store_->Insert(url, image_url2, src_image2);
    191 
    192   std::pair<gfx::Image, GURL> image_info = this->store_->Get(url);
    193 
    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));
    200 }
    201 
    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);
    207 
    208   this->ResetStore();
    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);
    216 
    217     EXPECT_EQ(image_url, image_info.second);
    218     EXPECT_TRUE(CompareImages(src_image, image_info.first));
    219   } else {
    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")));
    224   }
    225 }
    226 
    227 TYPED_TEST(ImageStoreUnitTest, GetSize) {
    228   gfx::Image src_image = GenerateBlackImage();
    229   const GURL url("foo://bar");
    230   const GURL image_url("a.jpg");
    231 
    232   int64 size = 0;
    233   if (this->use_persistent_store()) {
    234     // File shouldn't exist before we actually start using it since we do lazy
    235     // initialization.
    236     EXPECT_EQ(this->store_->GetStoreSizeInBytes(), -1);
    237   } else {
    238     EXPECT_LE(this->store_->GetStoreSizeInBytes(), 1024);
    239   }
    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();
    245   }
    246 
    247   if (this->use_persistent_store()) {
    248     EXPECT_GE(this->store_->GetStoreSizeInBytes(),  90 * 1024); //  90kb
    249     EXPECT_LE(this->store_->GetStoreSizeInBytes(), 200 * 1024); // 200kb
    250   } else {
    251     EXPECT_GE(this->store_->GetStoreSizeInBytes(), 400 * 1024); // 400kb
    252     EXPECT_LE(this->store_->GetStoreSizeInBytes(), 500 * 1024); // 500kb
    253   }
    254 }
    255 
    256 }  // namespace
    257