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 "base/thread_task_runner_handle.h"
10 #include "components/leveldb_proto/proto_database.h"
11 #include "components/leveldb_proto/testing/fake_db.h"
12 #include "components/suggestions/image_encoder.h"
13 #include "components/suggestions/image_fetcher.h"
14 #include "components/suggestions/image_fetcher_delegate.h"
15 #include "components/suggestions/image_manager.h"
16 #include "components/suggestions/proto/suggestions.pb.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19 #include "ui/gfx/image/image_skia.h"
22 using ::testing::Return
;
23 using ::testing::StrictMock
;
26 namespace suggestions
{
28 const char kTestUrl1
[] = "http://go.com/";
29 const char kTestUrl2
[] = "http://goal.com/";
30 const char kTestImagePath
[] = "files/image_decoding/droids.png";
31 const char kInvalidImagePath
[] = "files/DOESNOTEXIST";
33 using leveldb_proto::test::FakeDB
;
34 using suggestions::ImageData
;
35 using suggestions::ImageManager
;
37 typedef base::hash_map
<std::string
, ImageData
> EntryMap
;
39 void AddEntry(const ImageData
& d
, EntryMap
* map
) { (*map
)[d
.url()] = d
; }
41 class MockImageFetcher
: public suggestions::ImageFetcher
{
44 virtual ~MockImageFetcher() {}
45 MOCK_METHOD3(StartOrQueueNetworkRequest
,
46 void(const GURL
&, const GURL
&,
47 base::Callback
<void(const GURL
&, const SkBitmap
*)>));
48 MOCK_METHOD1(SetImageFetcherDelegate
, void(ImageFetcherDelegate
*));
51 class ImageManagerTest
: public testing::Test
{
54 : mock_image_fetcher_(NULL
),
55 num_callback_null_called_(0),
56 num_callback_valid_called_(0) {}
58 void SetUp() override
{
59 fake_db_
= new FakeDB
<ImageData
>(&db_model_
);
60 image_manager_
.reset(CreateImageManager(fake_db_
));
63 void TearDown() override
{
66 image_manager_
.reset();
69 void InitializeDefaultImageMapAndDatabase(ImageManager
* image_manager
,
70 FakeDB
<ImageData
>* fake_db
) {
74 suggestions::SuggestionsProfile suggestions_profile
;
75 suggestions::ChromeSuggestion
* suggestion
=
76 suggestions_profile
.add_suggestions();
77 suggestion
->set_url(kTestUrl1
);
78 suggestion
->set_thumbnail(kTestImagePath
);
80 image_manager
->Initialize(suggestions_profile
);
82 // Initialize empty database.
83 fake_db
->InitCallback(true);
84 fake_db
->LoadCallback(true);
87 ImageData
GetSampleImageData(const std::string
& url
) {
88 // Create test bitmap.
90 // Being careful with the Bitmap. There are memory-related issue in
92 bm
.allocN32Pixels(4, 4);
93 bm
.eraseColor(SK_ColorRED
);
96 std::vector
<unsigned char> encoded
;
97 EXPECT_TRUE(EncodeSkBitmapToJPEG(bm
, &encoded
));
98 data
.set_data(std::string(encoded
.begin(), encoded
.end()));
102 void OnImageAvailable(base::RunLoop
* loop
, const GURL
& url
,
103 const SkBitmap
* bitmap
) {
105 num_callback_valid_called_
++;
107 num_callback_null_called_
++;
112 ImageManager
* CreateImageManager(FakeDB
<ImageData
>* fake_db
) {
113 mock_image_fetcher_
= new StrictMock
<MockImageFetcher
>();
114 EXPECT_CALL(*mock_image_fetcher_
, SetImageFetcherDelegate(_
));
115 return new ImageManager(
116 scoped_ptr
<ImageFetcher
>(mock_image_fetcher_
),
117 scoped_ptr
<leveldb_proto::ProtoDatabase
<ImageData
>>(fake_db
),
118 FakeDB
<ImageData
>::DirectoryForTestDB(),
119 base::ThreadTaskRunnerHandle::Get());
123 // Owned by the ImageManager under test.
124 FakeDB
<ImageData
>* fake_db_
;
126 MockImageFetcher
* mock_image_fetcher_
;
128 int num_callback_null_called_
;
129 int num_callback_valid_called_
;
131 base::MessageLoop message_loop_
;
134 scoped_ptr
<ImageManager
> image_manager_
;
137 TEST_F(ImageManagerTest
, InitializeTest
) {
138 SuggestionsProfile suggestions_profile
;
139 ChromeSuggestion
* suggestion
= suggestions_profile
.add_suggestions();
140 suggestion
->set_url(kTestUrl1
);
141 suggestion
->set_thumbnail(kTestImagePath
);
143 image_manager_
->Initialize(suggestions_profile
);
146 EXPECT_TRUE(image_manager_
->GetImageURL(GURL(kTestUrl1
), &output
));
147 EXPECT_EQ(GURL(kTestImagePath
), output
);
149 EXPECT_FALSE(image_manager_
->GetImageURL(GURL("http://b.com"), &output
));
152 TEST_F(ImageManagerTest
, GetImageForURLNetwork
) {
153 InitializeDefaultImageMapAndDatabase(image_manager_
.get(), fake_db_
);
155 // We expect the fetcher to go to network and call the callback.
156 EXPECT_CALL(*mock_image_fetcher_
, StartOrQueueNetworkRequest(_
, _
, _
));
158 // Fetch existing URL.
159 base::RunLoop run_loop
;
160 image_manager_
->GetImageForURL(GURL(kTestUrl1
),
161 base::Bind(&ImageManagerTest::OnImageAvailable
,
162 base::Unretained(this), &run_loop
));
164 // Will not go to network and use the fetcher since URL is invalid.
165 // Fetch non-existing URL.
166 image_manager_
->GetImageForURL(GURL(kTestUrl2
),
167 base::Bind(&ImageManagerTest::OnImageAvailable
,
168 base::Unretained(this), &run_loop
));
171 EXPECT_EQ(1, num_callback_null_called_
);
174 TEST_F(ImageManagerTest
, GetImageForURLNetworkCacheHit
) {
175 SuggestionsProfile suggestions_profile
;
176 ChromeSuggestion
* suggestion
= suggestions_profile
.add_suggestions();
177 suggestion
->set_url(kTestUrl1
);
178 // The URL we set is invalid, to show that it will fail from network.
179 suggestion
->set_thumbnail(kInvalidImagePath
);
181 // Create the ImageManager with an added entry in the database.
182 AddEntry(GetSampleImageData(kTestUrl1
), &db_model_
);
183 FakeDB
<ImageData
>* fake_db
= new FakeDB
<ImageData
>(&db_model_
);
184 image_manager_
.reset(CreateImageManager(fake_db
));
185 image_manager_
->Initialize(suggestions_profile
);
186 fake_db
->InitCallback(true);
187 fake_db
->LoadCallback(true);
188 // Expect something in the cache.
190 image_manager_
->GetEncodedImageFromCache(GURL(kTestUrl1
));
191 EXPECT_NE(nullptr, encoded_image
);
193 base::RunLoop run_loop
;
194 image_manager_
->GetImageForURL(GURL(kTestUrl1
),
195 base::Bind(&ImageManagerTest::OnImageAvailable
,
196 base::Unretained(this), &run_loop
));
199 EXPECT_EQ(0, num_callback_null_called_
);
200 EXPECT_EQ(1, num_callback_valid_called_
);
203 } // namespace suggestions