blob: c52b54cee8001632cdd28690e5b7b58fa7bb6edc [file] [log] [blame]
mathpc3c8b0e2014-09-29 15:25:131// 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 <string>
6
7#include "base/files/file_path.h"
8#include "base/run_loop.h"
dskiba960b00e2015-06-11 22:44:469#include "base/thread_task_runner_handle.h"
mathpc3c8b0e2014-09-29 15:25:1310#include "components/leveldb_proto/proto_database.h"
11#include "components/leveldb_proto/testing/fake_db.h"
mathp3377c6262014-10-10 21:13:0012#include "components/suggestions/image_encoder.h"
mathpc3c8b0e2014-09-29 15:25:1313#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"
20#include "url/gurl.h"
21
22using ::testing::Return;
23using ::testing::StrictMock;
24using ::testing::_;
25
26namespace suggestions {
27
28const char kTestUrl1[] = "http://go.com/";
29const char kTestUrl2[] = "http://goal.com/";
30const char kTestImagePath[] = "files/image_decoding/droids.png";
31const char kInvalidImagePath[] = "files/DOESNOTEXIST";
32
33using leveldb_proto::test::FakeDB;
34using suggestions::ImageData;
35using suggestions::ImageManager;
36
37typedef base::hash_map<std::string, ImageData> EntryMap;
38
39void AddEntry(const ImageData& d, EntryMap* map) { (*map)[d.url()] = d; }
40
41class MockImageFetcher : public suggestions::ImageFetcher {
42 public:
43 MockImageFetcher() {}
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*));
49};
50
51class ImageManagerTest : public testing::Test {
52 public:
53 ImageManagerTest()
54 : mock_image_fetcher_(NULL),
55 num_callback_null_called_(0),
56 num_callback_valid_called_(0) {}
57
dcheng30a1b1542014-10-29 21:27:5058 void SetUp() override {
mathpc3c8b0e2014-09-29 15:25:1359 fake_db_ = new FakeDB<ImageData>(&db_model_);
mathp60143a32014-10-08 14:52:4560 image_manager_.reset(CreateImageManager(fake_db_));
mathpc3c8b0e2014-09-29 15:25:1361 }
62
dcheng30a1b1542014-10-29 21:27:5063 void TearDown() override {
mathpc3c8b0e2014-09-29 15:25:1364 fake_db_ = NULL;
65 db_model_.clear();
66 image_manager_.reset();
67 }
68
69 void InitializeDefaultImageMapAndDatabase(ImageManager* image_manager,
70 FakeDB<ImageData>* fake_db) {
71 CHECK(image_manager);
72 CHECK(fake_db);
73
74 suggestions::SuggestionsProfile suggestions_profile;
75 suggestions::ChromeSuggestion* suggestion =
76 suggestions_profile.add_suggestions();
77 suggestion->set_url(kTestUrl1);
78 suggestion->set_thumbnail(kTestImagePath);
79
80 image_manager->Initialize(suggestions_profile);
81
82 // Initialize empty database.
83 fake_db->InitCallback(true);
84 fake_db->LoadCallback(true);
85 }
86
87 ImageData GetSampleImageData(const std::string& url) {
88 // Create test bitmap.
89 SkBitmap bm;
90 // Being careful with the Bitmap. There are memory-related issue in
91 // crbug.com/101781.
92 bm.allocN32Pixels(4, 4);
93 bm.eraseColor(SK_ColorRED);
94 ImageData data;
95 data.set_url(url);
96 std::vector<unsigned char> encoded;
mathpa27b85e2014-10-10 19:19:5797 EXPECT_TRUE(EncodeSkBitmapToJPEG(bm, &encoded));
mathpc3c8b0e2014-09-29 15:25:1398 data.set_data(std::string(encoded.begin(), encoded.end()));
99 return data;
100 }
101
102 void OnImageAvailable(base::RunLoop* loop, const GURL& url,
103 const SkBitmap* bitmap) {
104 if (bitmap) {
105 num_callback_valid_called_++;
106 } else {
107 num_callback_null_called_++;
108 }
109 loop->Quit();
110 }
111
mathp60143a32014-10-08 14:52:45112 ImageManager* CreateImageManager(FakeDB<ImageData>* fake_db) {
mathpc3c8b0e2014-09-29 15:25:13113 mock_image_fetcher_ = new StrictMock<MockImageFetcher>();
114 EXPECT_CALL(*mock_image_fetcher_, SetImageFetcherDelegate(_));
115 return new ImageManager(
116 scoped_ptr<ImageFetcher>(mock_image_fetcher_),
dskiba960b00e2015-06-11 22:44:46117 scoped_ptr<leveldb_proto::ProtoDatabase<ImageData>>(fake_db),
118 FakeDB<ImageData>::DirectoryForTestDB(),
119 base::ThreadTaskRunnerHandle::Get());
mathpc3c8b0e2014-09-29 15:25:13120 }
121
122 EntryMap db_model_;
123 // Owned by the ImageManager under test.
124 FakeDB<ImageData>* fake_db_;
125
126 MockImageFetcher* mock_image_fetcher_;
127
128 int num_callback_null_called_;
129 int num_callback_valid_called_;
dskiba960b00e2015-06-11 22:44:46130
131 base::MessageLoop message_loop_;
132
mathpc3c8b0e2014-09-29 15:25:13133 // Under test.
134 scoped_ptr<ImageManager> image_manager_;
135};
136
137TEST_F(ImageManagerTest, InitializeTest) {
138 SuggestionsProfile suggestions_profile;
139 ChromeSuggestion* suggestion = suggestions_profile.add_suggestions();
140 suggestion->set_url(kTestUrl1);
141 suggestion->set_thumbnail(kTestImagePath);
142
143 image_manager_->Initialize(suggestions_profile);
144
145 GURL output;
146 EXPECT_TRUE(image_manager_->GetImageURL(GURL(kTestUrl1), &output));
147 EXPECT_EQ(GURL(kTestImagePath), output);
148
149 EXPECT_FALSE(image_manager_->GetImageURL(GURL("http://b.com"), &output));
150}
151
152TEST_F(ImageManagerTest, GetImageForURLNetwork) {
153 InitializeDefaultImageMapAndDatabase(image_manager_.get(), fake_db_);
154
155 // We expect the fetcher to go to network and call the callback.
156 EXPECT_CALL(*mock_image_fetcher_, StartOrQueueNetworkRequest(_, _, _));
157
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));
163
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));
169 run_loop.Run();
170
171 EXPECT_EQ(1, num_callback_null_called_);
172}
173
174TEST_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);
180
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_);
mathp60143a32014-10-08 14:52:45184 image_manager_.reset(CreateImageManager(fake_db));
mathpc3c8b0e2014-09-29 15:25:13185 image_manager_->Initialize(suggestions_profile);
186 fake_db->InitCallback(true);
187 fake_db->LoadCallback(true);
188 // Expect something in the cache.
dskiba960b00e2015-06-11 22:44:46189 auto encoded_image =
190 image_manager_->GetEncodedImageFromCache(GURL(kTestUrl1));
191 EXPECT_NE(nullptr, encoded_image);
mathpc3c8b0e2014-09-29 15:25:13192
193 base::RunLoop run_loop;
194 image_manager_->GetImageForURL(GURL(kTestUrl1),
195 base::Bind(&ImageManagerTest::OnImageAvailable,
196 base::Unretained(this), &run_loop));
197 run_loop.Run();
198
199 EXPECT_EQ(0, num_callback_null_called_);
200 EXPECT_EQ(1, num_callback_valid_called_);
201}
202
203} // namespace suggestions