Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(26)

Side by Side Diff: cc/tiles/image_controller_unittest.cc

Issue 2631453002: Revert of cc: Add image decode queue functionality to image manager. (Closed)
Patch Set: Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/tiles/image_controller.cc ('k') | cc/tiles/image_decode_cache.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/bind.h"
6 #include "base/optional.h"
7 #include "base/run_loop.h"
8 #include "base/test/test_simple_task_runner.h"
9 #include "base/threading/sequenced_task_runner_handle.h"
10 #include "cc/tiles/image_controller.h" 5 #include "cc/tiles/image_controller.h"
11 #include "cc/tiles/image_decode_cache.h" 6 #include "cc/tiles/image_decode_cache.h"
12 #include "testing/gtest/include/gtest/gtest.h" 7 #include "testing/gtest/include/gtest/gtest.h"
13 8
14 namespace cc { 9 namespace cc {
15 namespace {
16 10
17 class TestWorkerThread : public base::SimpleThread {
18 public:
19 TestWorkerThread()
20 : base::SimpleThread("test_worker_thread"), condition_(&lock_) {}
21
22 void Run() override {
23 for (;;) {
24 base::AutoLock hold(lock_);
25 if (shutdown_)
26 break;
27
28 if (queue_.empty()) {
29 condition_.Wait();
30 continue;
31 }
32
33 queue_.front().Run();
34 queue_.erase(queue_.begin());
35 }
36 }
37
38 void Shutdown() {
39 base::AutoLock hold(lock_);
40 shutdown_ = true;
41 condition_.Signal();
42 }
43
44 void PostTask(const base::Closure& task) {
45 base::AutoLock hold(lock_);
46 queue_.push_back(task);
47 condition_.Signal();
48 }
49
50 private:
51 base::Lock lock_;
52 base::ConditionVariable condition_;
53 std::vector<base::Closure> queue_;
54 bool shutdown_ = false;
55 };
56
57 class WorkerTaskRunner : public base::SequencedTaskRunner {
58 public:
59 WorkerTaskRunner() { thread_.Start(); }
60
61 bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
62 const base::Closure& task,
63 base::TimeDelta delay) override {
64 return PostDelayedTask(from_here, task, delay);
65 }
66
67 bool PostDelayedTask(const tracked_objects::Location& from_here,
68 const base::Closure& task,
69 base::TimeDelta delay) override {
70 thread_.PostTask(task);
71 return true;
72 }
73
74 bool RunsTasksOnCurrentThread() const override { return false; }
75
76 protected:
77 ~WorkerTaskRunner() override {
78 thread_.Shutdown();
79 thread_.Join();
80 }
81
82 TestWorkerThread thread_;
83 };
84
85 // Image decode cache with introspection!
86 class TestableCache : public ImageDecodeCache { 11 class TestableCache : public ImageDecodeCache {
87 public: 12 public:
88 ~TestableCache() override { EXPECT_EQ(number_of_refs_, 0); }
89
90 bool GetTaskForImageAndRef(const DrawImage& image, 13 bool GetTaskForImageAndRef(const DrawImage& image,
91 const TracingInfo& tracing_info, 14 const TracingInfo& tracing_info,
92 scoped_refptr<TileTask>* task) override { 15 scoped_refptr<TileTask>* task) override {
93 *task = task_to_use_; 16 *task = nullptr;
94 ++number_of_refs_; 17 ++number_of_refs_;
95 return true; 18 return true;
96 } 19 }
97 bool GetOutOfRasterDecodeTaskForImageAndRef(
98 const DrawImage& image,
99 scoped_refptr<TileTask>* task) override {
100 *task = task_to_use_;
101 ++number_of_refs_;
102 return true;
103 }
104 20
105 void UnrefImage(const DrawImage& image) override { 21 void UnrefImage(const DrawImage& image) override {
106 ASSERT_GT(number_of_refs_, 0); 22 ASSERT_GT(number_of_refs_, 0);
107 --number_of_refs_; 23 --number_of_refs_;
108 } 24 }
109 DecodedDrawImage GetDecodedImageForDraw(const DrawImage& image) override { 25 DecodedDrawImage GetDecodedImageForDraw(const DrawImage& image) override {
110 return DecodedDrawImage(nullptr, kNone_SkFilterQuality); 26 return DecodedDrawImage(nullptr, kNone_SkFilterQuality);
111 } 27 }
112 void DrawWithImageFinished(const DrawImage& image, 28 void DrawWithImageFinished(const DrawImage& image,
113 const DecodedDrawImage& decoded_image) override {} 29 const DecodedDrawImage& decoded_image) override {}
114 void ReduceCacheUsage() override {} 30 void ReduceCacheUsage() override {}
115 void SetShouldAggressivelyFreeResources( 31 void SetShouldAggressivelyFreeResources(
116 bool aggressively_free_resources) override {} 32 bool aggressively_free_resources) override {}
117 33
118 int number_of_refs() const { return number_of_refs_; } 34 int number_of_refs() const { return number_of_refs_; }
119 void SetTaskToUse(scoped_refptr<TileTask> task) { task_to_use_ = task; }
120 35
121 private: 36 private:
122 int number_of_refs_ = 0; 37 int number_of_refs_ = 0;
123 scoped_refptr<TileTask> task_to_use_;
124 }; 38 };
125 39
126 // A simple class that can receive decode callbacks. 40 TEST(ImageControllerTest, NullCacheUnrefsImages) {
127 class DecodeClient { 41 TestableCache cache;
128 public: 42 ImageController controller;
129 DecodeClient() {} 43 controller.SetImageDecodeCache(&cache);
130 void Callback(const base::Closure& quit_closure,
131 ImageController::ImageDecodeRequestId id) {
132 id_ = id;
133 quit_closure.Run();
134 }
135 44
136 ImageController::ImageDecodeRequestId id() { return id_; }
137
138 private:
139 ImageController::ImageDecodeRequestId id_ = 0;
140 };
141
142 // A dummy task that does nothing.
143 class SimpleTask : public TileTask {
144 public:
145 SimpleTask() : TileTask(true /* supports_concurrent_execution */) {
146 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
147 }
148
149 void RunOnWorkerThread() override {
150 EXPECT_FALSE(HasCompleted());
151 EXPECT_FALSE(thread_checker_.CalledOnValidThread());
152 has_run_ = true;
153 }
154 void OnTaskCompleted() override {
155 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
156 }
157
158 bool has_run() { return has_run_; }
159
160 private:
161 ~SimpleTask() override = default;
162
163 base::ThreadChecker thread_checker_;
164 bool has_run_ = false;
165
166 DISALLOW_COPY_AND_ASSIGN(SimpleTask);
167 };
168
169 // A task that blocks until instructed otherwise.
170 class BlockingTask : public TileTask {
171 public:
172 BlockingTask()
173 : TileTask(true /* supports_concurrent_execution */), run_cv_(&lock_) {
174 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
175 }
176
177 void RunOnWorkerThread() override {
178 EXPECT_FALSE(HasCompleted());
179 EXPECT_FALSE(thread_checker_.CalledOnValidThread());
180 base::AutoLock hold(lock_);
181 if (!can_run_)
182 run_cv_.Wait();
183 has_run_ = true;
184 }
185
186 void OnTaskCompleted() override {
187 EXPECT_TRUE(thread_checker_.CalledOnValidThread());
188 }
189
190 void AllowToRun() {
191 base::AutoLock hold(lock_);
192 can_run_ = true;
193 run_cv_.Signal();
194 }
195
196 bool has_run() { return has_run_; }
197
198 private:
199 ~BlockingTask() override = default;
200
201 base::ThreadChecker thread_checker_;
202 bool has_run_ = false;
203 base::Lock lock_;
204 base::ConditionVariable run_cv_;
205 bool can_run_ = false;
206
207 DISALLOW_COPY_AND_ASSIGN(BlockingTask);
208 };
209
210 // For tests that exercise image controller's thread, this is the timeout value
211 // to
212 // allow the worker thread to do its work.
213 int kDefaultTimeoutSeconds = 10;
214
215 class ImageControllerTest : public testing::Test {
216 public:
217 ImageControllerTest() : task_runner_(base::SequencedTaskRunnerHandle::Get()) {
218 bitmap_.allocN32Pixels(1, 1);
219 image_ = SkImage::MakeFromBitmap(bitmap_);
220 }
221 ~ImageControllerTest() override = default;
222
223 void SetUp() override {
224 worker_task_runner_ = make_scoped_refptr(new WorkerTaskRunner);
225 controller_.reset(
226 new ImageController(task_runner_.get(), worker_task_runner_));
227 cache_ = TestableCache();
228 controller_->SetImageDecodeCache(&cache_);
229 }
230
231 void TearDown() override {
232 controller_.reset();
233 worker_task_runner_ = nullptr;
234 }
235
236 base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
237 ImageController* controller() { return controller_.get(); }
238 TestableCache* cache() { return &cache_; }
239 sk_sp<const SkImage> image() const { return image_; }
240
241 // Timeout callback, which errors and exits the runloop.
242 static void Timeout(base::RunLoop* run_loop) {
243 ADD_FAILURE() << "Timeout.";
244 run_loop->Quit();
245 }
246
247 // Convenience method to run the run loop with a timeout.
248 void RunOrTimeout(base::RunLoop* run_loop) {
249 task_runner_->PostDelayedTask(
250 FROM_HERE,
251 base::Bind(&ImageControllerTest::Timeout, base::Unretained(run_loop)),
252 base::TimeDelta::FromSeconds(kDefaultTimeoutSeconds));
253 run_loop->Run();
254 }
255
256 private:
257 scoped_refptr<base::SequencedTaskRunner> task_runner_;
258 scoped_refptr<WorkerTaskRunner> worker_task_runner_;
259 TestableCache cache_;
260 std::unique_ptr<ImageController> controller_;
261 SkBitmap bitmap_;
262 sk_sp<const SkImage> image_;
263 };
264
265 TEST_F(ImageControllerTest, NullControllerUnrefsImages) {
266 std::vector<DrawImage> images(10); 45 std::vector<DrawImage> images(10);
267 ImageDecodeCache::TracingInfo tracing_info; 46 ImageDecodeCache::TracingInfo tracing_info;
268 47
269 ASSERT_EQ(10u, images.size()); 48 ASSERT_EQ(10u, images.size());
270 auto tasks = 49 auto tasks = controller.SetPredecodeImages(std::move(images), tracing_info);
271 controller()->SetPredecodeImages(std::move(images), tracing_info);
272 EXPECT_EQ(0u, tasks.size()); 50 EXPECT_EQ(0u, tasks.size());
273 EXPECT_EQ(10, cache()->number_of_refs()); 51 EXPECT_EQ(10, cache.number_of_refs());
274 52
275 controller()->SetImageDecodeCache(nullptr); 53 controller.SetImageDecodeCache(nullptr);
276 EXPECT_EQ(0, cache()->number_of_refs()); 54 EXPECT_EQ(0, cache.number_of_refs());
277 } 55 }
278 56
279 TEST_F(ImageControllerTest, QueueImageDecode) {
280 base::RunLoop run_loop;
281 DecodeClient decode_client;
282 EXPECT_EQ(image()->bounds().width(), 1);
283 ImageController::ImageDecodeRequestId expected_id =
284 controller()->QueueImageDecode(
285 image(),
286 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client),
287 run_loop.QuitClosure()));
288 RunOrTimeout(&run_loop);
289 EXPECT_EQ(expected_id, decode_client.id());
290 }
291
292 TEST_F(ImageControllerTest, QueueImageDecodeMultipleImages) {
293 base::RunLoop run_loop;
294 DecodeClient decode_client1;
295 ImageController::ImageDecodeRequestId expected_id1 =
296 controller()->QueueImageDecode(
297 image(),
298 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1),
299 base::Bind([] {})));
300 DecodeClient decode_client2;
301 ImageController::ImageDecodeRequestId expected_id2 =
302 controller()->QueueImageDecode(
303 image(),
304 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2),
305 base::Bind([] {})));
306 DecodeClient decode_client3;
307 ImageController::ImageDecodeRequestId expected_id3 =
308 controller()->QueueImageDecode(
309 image(),
310 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client3),
311 run_loop.QuitClosure()));
312 RunOrTimeout(&run_loop);
313 EXPECT_EQ(expected_id1, decode_client1.id());
314 EXPECT_EQ(expected_id2, decode_client2.id());
315 EXPECT_EQ(expected_id3, decode_client3.id());
316 }
317
318 TEST_F(ImageControllerTest, QueueImageDecodeWithTask) {
319 scoped_refptr<SimpleTask> task(new SimpleTask);
320 cache()->SetTaskToUse(task);
321
322 base::RunLoop run_loop;
323 DecodeClient decode_client;
324 ImageController::ImageDecodeRequestId expected_id =
325 controller()->QueueImageDecode(
326 image(),
327 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client),
328 run_loop.QuitClosure()));
329 RunOrTimeout(&run_loop);
330 EXPECT_EQ(expected_id, decode_client.id());
331 EXPECT_TRUE(task->has_run());
332 EXPECT_TRUE(task->HasCompleted());
333 }
334
335 TEST_F(ImageControllerTest, QueueImageDecodeMultipleImagesSameTask) {
336 scoped_refptr<SimpleTask> task(new SimpleTask);
337 cache()->SetTaskToUse(task);
338
339 base::RunLoop run_loop;
340 DecodeClient decode_client1;
341 ImageController::ImageDecodeRequestId expected_id1 =
342 controller()->QueueImageDecode(
343 image(),
344 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1),
345 base::Bind([] {})));
346 DecodeClient decode_client2;
347 ImageController::ImageDecodeRequestId expected_id2 =
348 controller()->QueueImageDecode(
349 image(),
350 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2),
351 base::Bind([] {})));
352 DecodeClient decode_client3;
353 ImageController::ImageDecodeRequestId expected_id3 =
354 controller()->QueueImageDecode(
355 image(),
356 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client3),
357 run_loop.QuitClosure()));
358 RunOrTimeout(&run_loop);
359 EXPECT_EQ(expected_id1, decode_client1.id());
360 EXPECT_EQ(expected_id2, decode_client2.id());
361 EXPECT_EQ(expected_id3, decode_client3.id());
362 EXPECT_TRUE(task->has_run());
363 EXPECT_TRUE(task->HasCompleted());
364 }
365
366 TEST_F(ImageControllerTest, QueueImageDecodeChangeControllerWithTaskQueued) {
367 scoped_refptr<BlockingTask> task_one(new BlockingTask);
368 cache()->SetTaskToUse(task_one);
369
370 DecodeClient decode_client1;
371 ImageController::ImageDecodeRequestId expected_id1 =
372 controller()->QueueImageDecode(
373 image(),
374 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1),
375 base::Bind([] {})));
376
377 scoped_refptr<BlockingTask> task_two(new BlockingTask);
378 cache()->SetTaskToUse(task_two);
379
380 base::RunLoop run_loop;
381 DecodeClient decode_client2;
382 ImageController::ImageDecodeRequestId expected_id2 =
383 controller()->QueueImageDecode(
384 image(),
385 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2),
386 run_loop.QuitClosure()));
387
388 task_one->AllowToRun();
389 task_two->AllowToRun();
390 controller()->SetImageDecodeCache(nullptr);
391
392 RunOrTimeout(&run_loop);
393
394 EXPECT_TRUE(task_one->state().IsCanceled() || task_one->HasCompleted());
395 EXPECT_TRUE(task_two->state().IsCanceled() || task_two->HasCompleted());
396 EXPECT_EQ(expected_id1, decode_client1.id());
397 EXPECT_EQ(expected_id2, decode_client2.id());
398 }
399
400 TEST_F(ImageControllerTest, QueueImageDecodeImageAlreadyLocked) {
401 scoped_refptr<SimpleTask> task(new SimpleTask);
402 cache()->SetTaskToUse(task);
403
404 base::RunLoop run_loop1;
405 DecodeClient decode_client1;
406 ImageController::ImageDecodeRequestId expected_id1 =
407 controller()->QueueImageDecode(
408 image(),
409 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1),
410 run_loop1.QuitClosure()));
411 RunOrTimeout(&run_loop1);
412 EXPECT_EQ(expected_id1, decode_client1.id());
413 EXPECT_TRUE(task->has_run());
414
415 cache()->SetTaskToUse(nullptr);
416 base::RunLoop run_loop2;
417 DecodeClient decode_client2;
418 ImageController::ImageDecodeRequestId expected_id2 =
419 controller()->QueueImageDecode(
420 image(),
421 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2),
422 run_loop2.QuitClosure()));
423 RunOrTimeout(&run_loop2);
424 EXPECT_EQ(expected_id2, decode_client2.id());
425 }
426
427 TEST_F(ImageControllerTest, QueueImageDecodeLockedImageControllerChange) {
428 scoped_refptr<SimpleTask> task(new SimpleTask);
429 cache()->SetTaskToUse(task);
430
431 base::RunLoop run_loop1;
432 DecodeClient decode_client1;
433 ImageController::ImageDecodeRequestId expected_id1 =
434 controller()->QueueImageDecode(
435 image(),
436 base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1),
437 run_loop1.QuitClosure()));
438 RunOrTimeout(&run_loop1);
439 EXPECT_EQ(expected_id1, decode_client1.id());
440 EXPECT_TRUE(task->has_run());
441 EXPECT_EQ(1, cache()->number_of_refs());
442
443 controller()->SetImageDecodeCache(nullptr);
444 EXPECT_EQ(0, cache()->number_of_refs());
445 }
446
447 } // namespace
448 } // namespace cc 57 } // namespace cc
OLDNEW
« no previous file with comments | « cc/tiles/image_controller.cc ('k') | cc/tiles/image_decode_cache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698