OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 "chrome/browser/media/combined_desktop_media_list.h" | |
6 | |
7 #include "base/message_loop/message_loop.h" | |
8 #include "base/single_thread_task_runner.h" | |
9 #include "base/strings/utf_string_conversions.h" | |
10 #include "chrome/browser/media/desktop_media_list_base.h" | |
11 #include "chrome/browser/media/desktop_media_list_observer.h" | |
12 #include "content/public/test/test_browser_thread.h" | |
13 #include "testing/gmock/include/gmock/gmock.h" | |
14 #include "testing/gtest/include/gtest/gtest.h" | |
15 #include "ui/gfx/image/image_skia.h" | |
16 | |
17 using testing::DoAll; | |
18 using content::DesktopMediaID; | |
19 | |
20 static const int kThumbnailSize = 50; | |
21 static const int kDefaultSouceCount = 2; // >=2. | |
qiangchen
2016/01/26 20:43:09
kDefaultSourceCount
GeorgeZ
2016/01/27 00:17:38
Done.
| |
22 | |
23 // Create a greyscale image with certain size and grayscale value. | |
24 gfx::ImageSkia CreateGrayscaleImage(gfx::Size size, int greyscale_value) { | |
25 SkBitmap result; | |
26 result.allocN32Pixels(size.width(), size.height(), true); | |
27 | |
28 result.lockPixels(); | |
29 uint8_t* pixels_data = reinterpret_cast<uint8_t*>(result.getPixels()); | |
30 | |
31 // Set greyscale value for all pixels. | |
32 for (int y = 0; y < result.height(); ++y) { | |
33 for (int x = 0; x < result.width(); ++x) { | |
34 pixels_data[result.rowBytes() * y + x * result.bytesPerPixel()] = | |
35 greyscale_value; | |
36 pixels_data[result.rowBytes() * y + x * result.bytesPerPixel() + 1] = | |
37 greyscale_value; | |
38 pixels_data[result.rowBytes() * y + x * result.bytesPerPixel() + 2] = | |
39 greyscale_value; | |
40 pixels_data[result.rowBytes() * y + x * result.bytesPerPixel() + 3] = | |
41 0xff; | |
42 } | |
43 } | |
44 | |
45 result.unlockPixels(); | |
46 | |
47 return gfx::ImageSkia::CreateFrom1xBitmap(result); | |
48 } | |
49 | |
50 // Fake Implementation of DesktopMediaListBase. | |
51 class FakeDesktopMediaListBaseImpl : public DesktopMediaListBase { | |
52 public: | |
53 explicit FakeDesktopMediaListBaseImpl(DesktopMediaID::Type type) | |
54 : DesktopMediaListBase(base::TimeDelta::FromMilliseconds(1)), | |
55 media_type_(type) { | |
56 SetThumbnailSize(gfx::Size(kThumbnailSize, kThumbnailSize)); | |
57 | |
58 for (int i = 0; i < kDefaultSouceCount; ++i) | |
59 AddFakeSource(i, base::UTF8ToUTF16("Test media"), | |
60 static_cast<uint8_t>(i)); | |
61 } | |
62 | |
63 ~FakeDesktopMediaListBaseImpl() override{}; | |
64 | |
65 void AddFakeSource(int index, base::string16 title, int greyscale_value) { | |
66 DesktopMediaID id(media_type_, index + 1); | |
67 fake_sources_.push_back(DesktopMediaListBase::SourceDescription(id, title)); | |
68 fake_thumbnails_.push_back( | |
69 CreateGrayscaleImage(gfx::Size(10, 10), greyscale_value)); | |
70 current_thumbnail_map_[id.id] = greyscale_value; | |
71 } | |
72 | |
73 void RemoveFakeSource(int index) { | |
74 if (static_cast<size_t>(index) >= fake_sources_.size()) | |
75 return; | |
76 | |
77 current_thumbnail_map_.erase(fake_sources_[index].id.id); | |
78 fake_sources_.erase(fake_sources_.begin() + index); | |
79 fake_thumbnails_.erase(fake_thumbnails_.begin() + index); | |
80 } | |
81 | |
82 private: | |
83 void Refresh() override { | |
84 UpdateSourcesList(fake_sources_); | |
85 | |
86 // Update thumbnails. | |
87 for (size_t i = 0; i < fake_sources_.size(); i++) { | |
88 // only update when a thumbnail is added or changed. | |
89 const int id = fake_sources_[i].id.id; | |
90 if (!refreshed_thumbnail_map_.count(id) || | |
91 (refreshed_thumbnail_map_[id] != current_thumbnail_map_[id])) { | |
92 UpdateSourceThumbnail(fake_sources_[i].id, fake_thumbnails_[i]); | |
93 } | |
94 } | |
95 refreshed_thumbnail_map_ = current_thumbnail_map_; | |
96 | |
97 ScheduleNextRefresh(); | |
98 } | |
99 | |
100 std::vector<DesktopMediaListBase::SourceDescription> fake_sources_; | |
101 std::vector<gfx::ImageSkia> fake_thumbnails_; | |
102 DesktopMediaID::Type media_type_; | |
103 // The current and last refrehed maps of source id and thumbnail's greyscale. | |
104 // They are used for detect the thumbnail add or change. | |
105 std::map<int, int> current_thumbnail_map_, refreshed_thumbnail_map_; | |
106 | |
107 DISALLOW_COPY_AND_ASSIGN(FakeDesktopMediaListBaseImpl); | |
108 }; | |
109 | |
110 class MockObserver : public DesktopMediaListObserver { | |
111 public: | |
112 MOCK_METHOD2(OnSourceAdded, void(DesktopMediaList* list, int index)); | |
113 MOCK_METHOD2(OnSourceRemoved, void(DesktopMediaList* list, int index)); | |
114 MOCK_METHOD3(OnSourceMoved, | |
115 void(DesktopMediaList* list, int old_index, int new_index)); | |
116 MOCK_METHOD2(OnSourceNameChanged, void(DesktopMediaList* list, int index)); | |
117 MOCK_METHOD2(OnSourceThumbnailChanged, | |
118 void(DesktopMediaList* list, int index)); | |
119 }; | |
120 | |
121 ACTION_P2(CheckListSize, list, expected_list_size) { | |
122 EXPECT_EQ(expected_list_size, list->GetSourceCount()); | |
123 } | |
124 | |
125 ACTION_P(QuitMessageLoop, message_loop) { | |
126 message_loop->task_runner()->PostTask( | |
127 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); | |
128 } | |
129 | |
130 class CombinedDesktopMediaListTest : public testing::Test { | |
131 public: | |
132 CombinedDesktopMediaListTest() | |
133 : ui_thread_(content::BrowserThread::UI, &message_loop_) { | |
134 list1_ = new FakeDesktopMediaListBaseImpl(DesktopMediaID::TYPE_SCREEN); | |
135 list2_ = new FakeDesktopMediaListBaseImpl(DesktopMediaID::TYPE_WINDOW); | |
136 | |
137 scoped_ptr<DesktopMediaList> list1(list1_); | |
138 scoped_ptr<DesktopMediaList> list2(list2_); | |
139 | |
140 std::vector<scoped_ptr<DesktopMediaList>> lists; | |
141 lists.push_back(std::move(list1)); | |
142 lists.push_back(std::move(list2)); | |
143 | |
144 combined_list_.reset(new CombinedDesktopMediaList(lists)); | |
145 } | |
146 | |
147 // StartUpdating() and verify the first call of refresh(). | |
148 void Verify() { | |
qiangchen
2016/01/26 20:43:09
This function is more like initialize than verify.
GeorgeZ
2016/01/27 00:17:38
Done.
| |
149 { | |
150 testing::InSequence dummy; | |
151 | |
152 // list1_'s refresh. | |
153 for (int i = 0; i < kDefaultSouceCount; ++i) { | |
154 EXPECT_CALL(observer_, OnSourceAdded(combined_list_.get(), i)) | |
155 .WillOnce(CheckListSize(combined_list_.get(), i + 1)); | |
156 } | |
157 | |
158 for (int i = 0; i < kDefaultSouceCount; ++i) { | |
159 EXPECT_CALL(observer_, | |
160 OnSourceThumbnailChanged(combined_list_.get(), i)); | |
161 } | |
162 | |
163 // list2_'s refresh. | |
164 for (int i = kDefaultSouceCount; i < 2 * kDefaultSouceCount; ++i) { | |
165 EXPECT_CALL(observer_, OnSourceAdded(combined_list_.get(), i)) | |
166 .WillOnce(CheckListSize(combined_list_.get(), i + 1)); | |
167 } | |
168 | |
169 for (int i = kDefaultSouceCount; i < 2 * kDefaultSouceCount - 1; ++i) { | |
170 EXPECT_CALL(observer_, | |
171 OnSourceThumbnailChanged(combined_list_.get(), i)); | |
172 } | |
173 | |
174 EXPECT_CALL(observer_, | |
175 OnSourceThumbnailChanged(combined_list_.get(), | |
176 2 * kDefaultSouceCount - 1)) | |
177 .WillOnce(QuitMessageLoop(&message_loop_)); | |
178 } | |
179 | |
180 combined_list_->StartUpdating(&observer_); | |
181 message_loop_.Run(); | |
182 | |
183 // list1_'s sources. | |
184 for (int i = 0; i < kDefaultSouceCount; ++i) { | |
185 EXPECT_EQ(combined_list_->GetSource(i).id.type, | |
186 content::DesktopMediaID::TYPE_SCREEN); | |
187 EXPECT_EQ(combined_list_->GetSource(i).id.id, i + 1); | |
188 } | |
189 | |
190 // list2_'s sources. | |
191 for (int i = kDefaultSouceCount; i < 2 * kDefaultSouceCount; i++) { | |
192 EXPECT_EQ(combined_list_->GetSource(i).id.type, | |
193 content::DesktopMediaID::TYPE_WINDOW); | |
194 EXPECT_EQ(combined_list_->GetSource(i).id.id, i - kDefaultSouceCount + 1); | |
195 } | |
196 | |
197 testing::Mock::VerifyAndClearExpectations(&observer_); | |
qiangchen
2016/01/26 20:43:09
This is unsafe, it is better to let observer_ to h
GeorgeZ
2016/01/27 00:17:38
Done.
| |
198 } | |
199 | |
200 protected: | |
201 // Must be listed before |combined_list_|, so it's destroyed last. | |
202 MockObserver observer_; | |
203 FakeDesktopMediaListBaseImpl* list1_; | |
204 FakeDesktopMediaListBaseImpl* list2_; | |
205 scoped_ptr<CombinedDesktopMediaList> combined_list_; | |
206 | |
207 base::MessageLoop message_loop_; | |
208 content::TestBrowserThread ui_thread_; | |
209 | |
210 DISALLOW_COPY_AND_ASSIGN(CombinedDesktopMediaListTest); | |
211 }; | |
212 | |
213 TEST_F(CombinedDesktopMediaListTest, AddSource) { | |
214 Verify(); | |
215 | |
216 int index = kDefaultSouceCount; | |
217 list1_->AddFakeSource(index, base::UTF8ToUTF16("Test media"), | |
218 static_cast<uint8_t>(index)); | |
219 | |
220 EXPECT_CALL(observer_, OnSourceAdded(combined_list_.get(), index)) | |
221 .WillOnce( | |
222 CheckListSize(combined_list_.get(), 2 * kDefaultSouceCount + 1)); | |
223 EXPECT_CALL(observer_, OnSourceThumbnailChanged(combined_list_.get(), index)) | |
224 .WillOnce(QuitMessageLoop(&message_loop_)); | |
225 | |
226 message_loop_.Run(); | |
227 | |
228 list2_->AddFakeSource(index, base::UTF8ToUTF16("Test media"), | |
229 static_cast<uint8_t>(index)); | |
230 | |
231 EXPECT_CALL(observer_, | |
232 OnSourceAdded(combined_list_.get(), 2 * kDefaultSouceCount + 1)) | |
233 .WillOnce( | |
234 CheckListSize(combined_list_.get(), 2 * kDefaultSouceCount + 2)); | |
235 EXPECT_CALL(observer_, OnSourceThumbnailChanged(combined_list_.get(), | |
236 2 * kDefaultSouceCount + 1)) | |
237 .WillOnce(QuitMessageLoop(&message_loop_)); | |
238 | |
239 message_loop_.Run(); | |
240 | |
241 // Verify last source for list1_ and first source for list2_. | |
242 EXPECT_EQ(combined_list_->GetSource(index).id.type, | |
243 content::DesktopMediaID::TYPE_SCREEN); | |
244 EXPECT_EQ(combined_list_->GetSource(index).id.id, index + 1); | |
245 EXPECT_EQ(combined_list_->GetSource(index + 1).id.type, | |
246 content::DesktopMediaID::TYPE_WINDOW); | |
247 EXPECT_EQ(combined_list_->GetSource(index + 1).id.id, 1); | |
248 } | |
249 | |
250 TEST_F(CombinedDesktopMediaListTest, RemoveSource) { | |
251 Verify(); | |
252 | |
253 int index = kDefaultSouceCount - 1; | |
254 list1_->RemoveFakeSource(index); | |
255 | |
256 EXPECT_CALL(observer_, OnSourceRemoved(combined_list_.get(), index)) | |
257 .WillOnce( | |
258 DoAll(CheckListSize(combined_list_.get(), 2 * kDefaultSouceCount - 1), | |
259 QuitMessageLoop(&message_loop_))); | |
260 | |
261 message_loop_.Run(); | |
262 | |
263 list2_->RemoveFakeSource(index); | |
264 | |
265 EXPECT_CALL(observer_, | |
266 OnSourceRemoved(combined_list_.get(), 2 * kDefaultSouceCount - 2)) | |
267 .WillOnce( | |
268 DoAll(CheckListSize(combined_list_.get(), 2 * kDefaultSouceCount - 2), | |
269 QuitMessageLoop(&message_loop_))); | |
270 | |
271 message_loop_.Run(); | |
272 | |
273 // Verify last source for list1_ and first source for list2_. | |
274 EXPECT_EQ(combined_list_->GetSource(index - 1).id.type, | |
275 content::DesktopMediaID::TYPE_SCREEN); | |
276 EXPECT_EQ(combined_list_->GetSource(index - 1).id.id, index); | |
277 EXPECT_EQ(combined_list_->GetSource(index).id.type, | |
278 content::DesktopMediaID::TYPE_WINDOW); | |
279 EXPECT_EQ(combined_list_->GetSource(index).id.id, 1); | |
280 } | |
281 | |
282 TEST_F(CombinedDesktopMediaListTest, MoveSource) { | |
283 Verify(); | |
284 | |
285 // Swap sources. | |
286 list1_->RemoveFakeSource(kDefaultSouceCount - 1); | |
287 list1_->RemoveFakeSource(kDefaultSouceCount - 2); | |
288 list1_->AddFakeSource(kDefaultSouceCount - 1, base::UTF8ToUTF16("Test media"), | |
289 static_cast<uint8_t>(kDefaultSouceCount - 1)); | |
290 list1_->AddFakeSource(kDefaultSouceCount - 2, base::UTF8ToUTF16("Test media"), | |
291 static_cast<uint8_t>(kDefaultSouceCount - 2)); | |
292 | |
293 EXPECT_CALL(observer_, | |
294 OnSourceMoved(combined_list_.get(), kDefaultSouceCount - 1, | |
295 kDefaultSouceCount - 2)) | |
296 .WillOnce(QuitMessageLoop(&message_loop_)); | |
297 | |
298 message_loop_.Run(); | |
299 | |
300 // Swap sources. | |
301 list2_->RemoveFakeSource(kDefaultSouceCount - 1); | |
302 list2_->RemoveFakeSource(kDefaultSouceCount - 2); | |
303 list2_->AddFakeSource(kDefaultSouceCount - 1, base::UTF8ToUTF16("Test media"), | |
304 static_cast<uint8_t>(kDefaultSouceCount - 1)); | |
305 list2_->AddFakeSource(kDefaultSouceCount - 2, base::UTF8ToUTF16("Test media"), | |
306 static_cast<uint8_t>(kDefaultSouceCount - 2)); | |
307 | |
308 EXPECT_CALL(observer_, | |
309 OnSourceMoved(combined_list_.get(), 2 * kDefaultSouceCount - 1, | |
310 2 * kDefaultSouceCount - 2)) | |
311 .WillOnce(QuitMessageLoop(&message_loop_)); | |
312 | |
313 message_loop_.Run(); | |
314 } | |
315 | |
316 TEST_F(CombinedDesktopMediaListTest, UpdateTitle) { | |
317 Verify(); | |
318 | |
319 // Change title. | |
320 list1_->RemoveFakeSource(kDefaultSouceCount - 1); | |
321 list1_->AddFakeSource(kDefaultSouceCount - 1, | |
322 base::UTF8ToUTF16("New test media"), | |
323 static_cast<uint8_t>(kDefaultSouceCount - 1)); | |
324 | |
325 EXPECT_CALL(observer_, | |
326 OnSourceNameChanged(combined_list_.get(), kDefaultSouceCount - 1)) | |
327 .WillOnce(QuitMessageLoop(&message_loop_)); | |
328 | |
329 message_loop_.Run(); | |
330 | |
331 // Change title. | |
332 list2_->RemoveFakeSource(kDefaultSouceCount - 1); | |
333 list2_->AddFakeSource(kDefaultSouceCount - 1, | |
334 base::UTF8ToUTF16("New test media"), | |
335 static_cast<uint8_t>(kDefaultSouceCount - 1)); | |
336 | |
337 EXPECT_CALL(observer_, OnSourceNameChanged(combined_list_.get(), | |
338 2 * kDefaultSouceCount - 1)) | |
339 .WillOnce(QuitMessageLoop(&message_loop_)); | |
340 | |
341 message_loop_.Run(); | |
342 | |
343 EXPECT_EQ(combined_list_->GetSource(kDefaultSouceCount - 1).name, | |
344 base::UTF8ToUTF16("New test media")); | |
345 EXPECT_EQ(combined_list_->GetSource(2 * kDefaultSouceCount - 1).name, | |
346 base::UTF8ToUTF16("New test media")); | |
347 } | |
348 | |
349 TEST_F(CombinedDesktopMediaListTest, UpdateThumbnail) { | |
350 Verify(); | |
351 | |
352 // Change thumbnail. | |
353 list1_->RemoveFakeSource(kDefaultSouceCount - 1); | |
354 list1_->AddFakeSource(kDefaultSouceCount - 1, base::UTF8ToUTF16("Test media"), | |
355 100); | |
356 | |
357 EXPECT_CALL(observer_, OnSourceThumbnailChanged(combined_list_.get(), | |
358 kDefaultSouceCount - 1)) | |
359 .WillOnce(QuitMessageLoop(&message_loop_)); | |
360 | |
361 message_loop_.Run(); | |
362 | |
363 // Change thumbnail. | |
364 list2_->RemoveFakeSource(kDefaultSouceCount - 1); | |
365 list2_->AddFakeSource(kDefaultSouceCount - 1, base::UTF8ToUTF16("Test media"), | |
366 100); | |
367 | |
368 EXPECT_CALL(observer_, OnSourceThumbnailChanged(combined_list_.get(), | |
369 2 * kDefaultSouceCount - 1)) | |
370 .WillOnce(QuitMessageLoop(&message_loop_)); | |
371 | |
372 message_loop_.Run(); | |
373 } | |
OLD | NEW |