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.
7 #include "base/files/file_path.h"
8 #include "base/run_loop.h"
9 #include "components/leveldb_proto/proto_database.h"
10 #include "components/leveldb_proto/testing/fake_db.h"
11 #include "components/suggestions/image_encoder.h"
12 #include "components/suggestions/image_fetcher.h"
13 #include "components/suggestions/image_fetcher_delegate.h"
14 #include "components/suggestions/image_manager.h"
15 #include "components/suggestions/proto/suggestions.pb.h"
16 #include "testing/gmock/include/gmock/gmock.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "ui/gfx/image/image_skia.h"
21 using ::testing::Return
;
22 using ::testing::StrictMock
;
25 namespace suggestions
{
27 const char kTestUrl1
[] = "http://go.com/";
28 const char kTestUrl2
[] = "http://goal.com/";
29 const char kTestImagePath
[] = "files/image_decoding/droids.png";
30 const char kInvalidImagePath
[] = "files/DOESNOTEXIST";
32 using leveldb_proto::test::FakeDB
;
33 using suggestions::ImageData
;
34 using suggestions::ImageManager
;
36 typedef base::hash_map
<std::string
, ImageData
> EntryMap
;
38 void AddEntry(const ImageData
& d
, EntryMap
* map
) { (*map
)[d
.url()] = d
; }
40 class MockImageFetcher
: public suggestions::ImageFetcher
{
43 virtual ~MockImageFetcher() {}
44 MOCK_METHOD3(StartOrQueueNetworkRequest
,
45 void(const GURL
&, const GURL
&,
46 base::Callback
<void(const GURL
&, const SkBitmap
*)>));
47 MOCK_METHOD1(SetImageFetcherDelegate
, void(ImageFetcherDelegate
*));
50 class ImageManagerTest
: public testing::Test
{
53 : mock_image_fetcher_(NULL
),
54 num_callback_null_called_(0),
55 num_callback_valid_called_(0) {}
57 void SetUp() override
{
58 fake_db_
= new FakeDB
<ImageData
>(&db_model_
);
59 image_manager_
.reset(CreateImageManager(fake_db_
));
62 void TearDown() override
{
65 image_manager_
.reset();
68 void InitializeDefaultImageMapAndDatabase(ImageManager
* image_manager
,
69 FakeDB
<ImageData
>* fake_db
) {
73 suggestions::SuggestionsProfile suggestions_profile
;
74 suggestions::ChromeSuggestion
* suggestion
=
75 suggestions_profile
.add_suggestions();
76 suggestion
->set_url(kTestUrl1
);
77 suggestion
->set_thumbnail(kTestImagePath
);
79 image_manager
->Initialize(suggestions_profile
);
81 // Initialize empty database.
82 fake_db
->InitCallback(true);
83 fake_db
->LoadCallback(true);
86 ImageData
GetSampleImageData(const std::string
& url
) {
87 // Create test bitmap.
89 // Being careful with the Bitmap. There are memory-related issue in
91 bm
.allocN32Pixels(4, 4);
92 bm
.eraseColor(SK_ColorRED
);
95 std::vector
<unsigned char> encoded
;
96 EXPECT_TRUE(EncodeSkBitmapToJPEG(bm
, &encoded
));
97 data
.set_data(std::string(encoded
.begin(), encoded
.end()));
101 void OnImageAvailable(base::RunLoop
* loop
, const GURL
& url
,
102 const SkBitmap
* bitmap
) {
104 num_callback_valid_called_
++;
106 num_callback_null_called_
++;
111 ImageManager
* CreateImageManager(FakeDB
<ImageData
>* fake_db
) {
112 mock_image_fetcher_
= new StrictMock
<MockImageFetcher
>();
113 EXPECT_CALL(*mock_image_fetcher_
, SetImageFetcherDelegate(_
));
114 return new ImageManager(
115 scoped_ptr
<ImageFetcher
>(mock_image_fetcher_
),
116 scoped_ptr
<leveldb_proto::ProtoDatabase
<ImageData
> >(fake_db
),
117 FakeDB
<ImageData
>::DirectoryForTestDB());
121 // Owned by the ImageManager under test.
122 FakeDB
<ImageData
>* fake_db_
;
124 MockImageFetcher
* mock_image_fetcher_
;
126 int num_callback_null_called_
;
127 int num_callback_valid_called_
;
129 scoped_ptr
<ImageManager
> image_manager_
;
132 TEST_F(ImageManagerTest
, InitializeTest
) {
133 SuggestionsProfile suggestions_profile
;
134 ChromeSuggestion
* suggestion
= suggestions_profile
.add_suggestions();
135 suggestion
->set_url(kTestUrl1
);
136 suggestion
->set_thumbnail(kTestImagePath
);
138 image_manager_
->Initialize(suggestions_profile
);
141 EXPECT_TRUE(image_manager_
->GetImageURL(GURL(kTestUrl1
), &output
));
142 EXPECT_EQ(GURL(kTestImagePath
), output
);
144 EXPECT_FALSE(image_manager_
->GetImageURL(GURL("http://b.com"), &output
));
147 TEST_F(ImageManagerTest
, GetImageForURLNetwork
) {
148 InitializeDefaultImageMapAndDatabase(image_manager_
.get(), fake_db_
);
150 // We expect the fetcher to go to network and call the callback.
151 EXPECT_CALL(*mock_image_fetcher_
, StartOrQueueNetworkRequest(_
, _
, _
));
153 // Fetch existing URL.
154 base::RunLoop run_loop
;
155 image_manager_
->GetImageForURL(GURL(kTestUrl1
),
156 base::Bind(&ImageManagerTest::OnImageAvailable
,
157 base::Unretained(this), &run_loop
));
159 // Will not go to network and use the fetcher since URL is invalid.
160 // Fetch non-existing URL.
161 image_manager_
->GetImageForURL(GURL(kTestUrl2
),
162 base::Bind(&ImageManagerTest::OnImageAvailable
,
163 base::Unretained(this), &run_loop
));
166 EXPECT_EQ(1, num_callback_null_called_
);
169 TEST_F(ImageManagerTest
, GetImageForURLNetworkCacheHit
) {
170 SuggestionsProfile suggestions_profile
;
171 ChromeSuggestion
* suggestion
= suggestions_profile
.add_suggestions();
172 suggestion
->set_url(kTestUrl1
);
173 // The URL we set is invalid, to show that it will fail from network.
174 suggestion
->set_thumbnail(kInvalidImagePath
);
176 // Create the ImageManager with an added entry in the database.
177 AddEntry(GetSampleImageData(kTestUrl1
), &db_model_
);
178 FakeDB
<ImageData
>* fake_db
= new FakeDB
<ImageData
>(&db_model_
);
179 image_manager_
.reset(CreateImageManager(fake_db
));
180 image_manager_
->Initialize(suggestions_profile
);
181 fake_db
->InitCallback(true);
182 fake_db
->LoadCallback(true);
183 // Expect something in the cache.
184 SkBitmap
* bitmap
= image_manager_
->GetBitmapFromCache(GURL(kTestUrl1
));
185 EXPECT_FALSE(bitmap
->isNull());
187 base::RunLoop run_loop
;
188 image_manager_
->GetImageForURL(GURL(kTestUrl1
),
189 base::Bind(&ImageManagerTest::OnImageAvailable
,
190 base::Unretained(this), &run_loop
));
193 EXPECT_EQ(0, num_callback_null_called_
);
194 EXPECT_EQ(1, num_callback_valid_called_
);
197 } // namespace suggestions