Index: cc/tiles/image_controller_unittest.cc |
diff --git a/cc/tiles/image_controller_unittest.cc b/cc/tiles/image_controller_unittest.cc |
index 945dce09e68d36614ee62ff73764cb3b82a583cd..fd9841cdd59844c2b89f3ce4f04d853aa3dd7555 100644 |
--- a/cc/tiles/image_controller_unittest.cc |
+++ b/cc/tiles/image_controller_unittest.cc |
@@ -2,102 +2,18 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "base/bind.h" |
-#include "base/optional.h" |
-#include "base/run_loop.h" |
-#include "base/test/test_simple_task_runner.h" |
-#include "base/threading/sequenced_task_runner_handle.h" |
#include "cc/tiles/image_controller.h" |
#include "cc/tiles/image_decode_cache.h" |
#include "testing/gtest/include/gtest/gtest.h" |
namespace cc { |
-namespace { |
-class TestWorkerThread : public base::SimpleThread { |
- public: |
- TestWorkerThread() |
- : base::SimpleThread("test_worker_thread"), condition_(&lock_) {} |
- |
- void Run() override { |
- for (;;) { |
- base::AutoLock hold(lock_); |
- if (shutdown_) |
- break; |
- |
- if (queue_.empty()) { |
- condition_.Wait(); |
- continue; |
- } |
- |
- queue_.front().Run(); |
- queue_.erase(queue_.begin()); |
- } |
- } |
- |
- void Shutdown() { |
- base::AutoLock hold(lock_); |
- shutdown_ = true; |
- condition_.Signal(); |
- } |
- |
- void PostTask(const base::Closure& task) { |
- base::AutoLock hold(lock_); |
- queue_.push_back(task); |
- condition_.Signal(); |
- } |
- |
- private: |
- base::Lock lock_; |
- base::ConditionVariable condition_; |
- std::vector<base::Closure> queue_; |
- bool shutdown_ = false; |
-}; |
- |
-class WorkerTaskRunner : public base::SequencedTaskRunner { |
- public: |
- WorkerTaskRunner() { thread_.Start(); } |
- |
- bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |
- const base::Closure& task, |
- base::TimeDelta delay) override { |
- return PostDelayedTask(from_here, task, delay); |
- } |
- |
- bool PostDelayedTask(const tracked_objects::Location& from_here, |
- const base::Closure& task, |
- base::TimeDelta delay) override { |
- thread_.PostTask(task); |
- return true; |
- } |
- |
- bool RunsTasksOnCurrentThread() const override { return false; } |
- |
- protected: |
- ~WorkerTaskRunner() override { |
- thread_.Shutdown(); |
- thread_.Join(); |
- } |
- |
- TestWorkerThread thread_; |
-}; |
- |
-// Image decode cache with introspection! |
class TestableCache : public ImageDecodeCache { |
public: |
- ~TestableCache() override { EXPECT_EQ(number_of_refs_, 0); } |
- |
bool GetTaskForImageAndRef(const DrawImage& image, |
const TracingInfo& tracing_info, |
scoped_refptr<TileTask>* task) override { |
- *task = task_to_use_; |
- ++number_of_refs_; |
- return true; |
- } |
- bool GetOutOfRasterDecodeTaskForImageAndRef( |
- const DrawImage& image, |
- scoped_refptr<TileTask>* task) override { |
- *task = task_to_use_; |
+ *task = nullptr; |
++number_of_refs_; |
return true; |
} |
@@ -116,333 +32,26 @@ |
bool aggressively_free_resources) override {} |
int number_of_refs() const { return number_of_refs_; } |
- void SetTaskToUse(scoped_refptr<TileTask> task) { task_to_use_ = task; } |
private: |
int number_of_refs_ = 0; |
- scoped_refptr<TileTask> task_to_use_; |
}; |
-// A simple class that can receive decode callbacks. |
-class DecodeClient { |
- public: |
- DecodeClient() {} |
- void Callback(const base::Closure& quit_closure, |
- ImageController::ImageDecodeRequestId id) { |
- id_ = id; |
- quit_closure.Run(); |
- } |
+TEST(ImageControllerTest, NullCacheUnrefsImages) { |
+ TestableCache cache; |
+ ImageController controller; |
+ controller.SetImageDecodeCache(&cache); |
- ImageController::ImageDecodeRequestId id() { return id_; } |
- |
- private: |
- ImageController::ImageDecodeRequestId id_ = 0; |
-}; |
- |
-// A dummy task that does nothing. |
-class SimpleTask : public TileTask { |
- public: |
- SimpleTask() : TileTask(true /* supports_concurrent_execution */) { |
- EXPECT_TRUE(thread_checker_.CalledOnValidThread()); |
- } |
- |
- void RunOnWorkerThread() override { |
- EXPECT_FALSE(HasCompleted()); |
- EXPECT_FALSE(thread_checker_.CalledOnValidThread()); |
- has_run_ = true; |
- } |
- void OnTaskCompleted() override { |
- EXPECT_TRUE(thread_checker_.CalledOnValidThread()); |
- } |
- |
- bool has_run() { return has_run_; } |
- |
- private: |
- ~SimpleTask() override = default; |
- |
- base::ThreadChecker thread_checker_; |
- bool has_run_ = false; |
- |
- DISALLOW_COPY_AND_ASSIGN(SimpleTask); |
-}; |
- |
-// A task that blocks until instructed otherwise. |
-class BlockingTask : public TileTask { |
- public: |
- BlockingTask() |
- : TileTask(true /* supports_concurrent_execution */), run_cv_(&lock_) { |
- EXPECT_TRUE(thread_checker_.CalledOnValidThread()); |
- } |
- |
- void RunOnWorkerThread() override { |
- EXPECT_FALSE(HasCompleted()); |
- EXPECT_FALSE(thread_checker_.CalledOnValidThread()); |
- base::AutoLock hold(lock_); |
- if (!can_run_) |
- run_cv_.Wait(); |
- has_run_ = true; |
- } |
- |
- void OnTaskCompleted() override { |
- EXPECT_TRUE(thread_checker_.CalledOnValidThread()); |
- } |
- |
- void AllowToRun() { |
- base::AutoLock hold(lock_); |
- can_run_ = true; |
- run_cv_.Signal(); |
- } |
- |
- bool has_run() { return has_run_; } |
- |
- private: |
- ~BlockingTask() override = default; |
- |
- base::ThreadChecker thread_checker_; |
- bool has_run_ = false; |
- base::Lock lock_; |
- base::ConditionVariable run_cv_; |
- bool can_run_ = false; |
- |
- DISALLOW_COPY_AND_ASSIGN(BlockingTask); |
-}; |
- |
-// For tests that exercise image controller's thread, this is the timeout value |
-// to |
-// allow the worker thread to do its work. |
-int kDefaultTimeoutSeconds = 10; |
- |
-class ImageControllerTest : public testing::Test { |
- public: |
- ImageControllerTest() : task_runner_(base::SequencedTaskRunnerHandle::Get()) { |
- bitmap_.allocN32Pixels(1, 1); |
- image_ = SkImage::MakeFromBitmap(bitmap_); |
- } |
- ~ImageControllerTest() override = default; |
- |
- void SetUp() override { |
- worker_task_runner_ = make_scoped_refptr(new WorkerTaskRunner); |
- controller_.reset( |
- new ImageController(task_runner_.get(), worker_task_runner_)); |
- cache_ = TestableCache(); |
- controller_->SetImageDecodeCache(&cache_); |
- } |
- |
- void TearDown() override { |
- controller_.reset(); |
- worker_task_runner_ = nullptr; |
- } |
- |
- base::SequencedTaskRunner* task_runner() { return task_runner_.get(); } |
- ImageController* controller() { return controller_.get(); } |
- TestableCache* cache() { return &cache_; } |
- sk_sp<const SkImage> image() const { return image_; } |
- |
- // Timeout callback, which errors and exits the runloop. |
- static void Timeout(base::RunLoop* run_loop) { |
- ADD_FAILURE() << "Timeout."; |
- run_loop->Quit(); |
- } |
- |
- // Convenience method to run the run loop with a timeout. |
- void RunOrTimeout(base::RunLoop* run_loop) { |
- task_runner_->PostDelayedTask( |
- FROM_HERE, |
- base::Bind(&ImageControllerTest::Timeout, base::Unretained(run_loop)), |
- base::TimeDelta::FromSeconds(kDefaultTimeoutSeconds)); |
- run_loop->Run(); |
- } |
- |
- private: |
- scoped_refptr<base::SequencedTaskRunner> task_runner_; |
- scoped_refptr<WorkerTaskRunner> worker_task_runner_; |
- TestableCache cache_; |
- std::unique_ptr<ImageController> controller_; |
- SkBitmap bitmap_; |
- sk_sp<const SkImage> image_; |
-}; |
- |
-TEST_F(ImageControllerTest, NullControllerUnrefsImages) { |
std::vector<DrawImage> images(10); |
ImageDecodeCache::TracingInfo tracing_info; |
ASSERT_EQ(10u, images.size()); |
- auto tasks = |
- controller()->SetPredecodeImages(std::move(images), tracing_info); |
+ auto tasks = controller.SetPredecodeImages(std::move(images), tracing_info); |
EXPECT_EQ(0u, tasks.size()); |
- EXPECT_EQ(10, cache()->number_of_refs()); |
+ EXPECT_EQ(10, cache.number_of_refs()); |
- controller()->SetImageDecodeCache(nullptr); |
- EXPECT_EQ(0, cache()->number_of_refs()); |
+ controller.SetImageDecodeCache(nullptr); |
+ EXPECT_EQ(0, cache.number_of_refs()); |
} |
-TEST_F(ImageControllerTest, QueueImageDecode) { |
- base::RunLoop run_loop; |
- DecodeClient decode_client; |
- EXPECT_EQ(image()->bounds().width(), 1); |
- ImageController::ImageDecodeRequestId expected_id = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client), |
- run_loop.QuitClosure())); |
- RunOrTimeout(&run_loop); |
- EXPECT_EQ(expected_id, decode_client.id()); |
-} |
- |
-TEST_F(ImageControllerTest, QueueImageDecodeMultipleImages) { |
- base::RunLoop run_loop; |
- DecodeClient decode_client1; |
- ImageController::ImageDecodeRequestId expected_id1 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), |
- base::Bind([] {}))); |
- DecodeClient decode_client2; |
- ImageController::ImageDecodeRequestId expected_id2 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), |
- base::Bind([] {}))); |
- DecodeClient decode_client3; |
- ImageController::ImageDecodeRequestId expected_id3 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client3), |
- run_loop.QuitClosure())); |
- RunOrTimeout(&run_loop); |
- EXPECT_EQ(expected_id1, decode_client1.id()); |
- EXPECT_EQ(expected_id2, decode_client2.id()); |
- EXPECT_EQ(expected_id3, decode_client3.id()); |
-} |
- |
-TEST_F(ImageControllerTest, QueueImageDecodeWithTask) { |
- scoped_refptr<SimpleTask> task(new SimpleTask); |
- cache()->SetTaskToUse(task); |
- |
- base::RunLoop run_loop; |
- DecodeClient decode_client; |
- ImageController::ImageDecodeRequestId expected_id = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client), |
- run_loop.QuitClosure())); |
- RunOrTimeout(&run_loop); |
- EXPECT_EQ(expected_id, decode_client.id()); |
- EXPECT_TRUE(task->has_run()); |
- EXPECT_TRUE(task->HasCompleted()); |
-} |
- |
-TEST_F(ImageControllerTest, QueueImageDecodeMultipleImagesSameTask) { |
- scoped_refptr<SimpleTask> task(new SimpleTask); |
- cache()->SetTaskToUse(task); |
- |
- base::RunLoop run_loop; |
- DecodeClient decode_client1; |
- ImageController::ImageDecodeRequestId expected_id1 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), |
- base::Bind([] {}))); |
- DecodeClient decode_client2; |
- ImageController::ImageDecodeRequestId expected_id2 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), |
- base::Bind([] {}))); |
- DecodeClient decode_client3; |
- ImageController::ImageDecodeRequestId expected_id3 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client3), |
- run_loop.QuitClosure())); |
- RunOrTimeout(&run_loop); |
- EXPECT_EQ(expected_id1, decode_client1.id()); |
- EXPECT_EQ(expected_id2, decode_client2.id()); |
- EXPECT_EQ(expected_id3, decode_client3.id()); |
- EXPECT_TRUE(task->has_run()); |
- EXPECT_TRUE(task->HasCompleted()); |
-} |
- |
-TEST_F(ImageControllerTest, QueueImageDecodeChangeControllerWithTaskQueued) { |
- scoped_refptr<BlockingTask> task_one(new BlockingTask); |
- cache()->SetTaskToUse(task_one); |
- |
- DecodeClient decode_client1; |
- ImageController::ImageDecodeRequestId expected_id1 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), |
- base::Bind([] {}))); |
- |
- scoped_refptr<BlockingTask> task_two(new BlockingTask); |
- cache()->SetTaskToUse(task_two); |
- |
- base::RunLoop run_loop; |
- DecodeClient decode_client2; |
- ImageController::ImageDecodeRequestId expected_id2 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), |
- run_loop.QuitClosure())); |
- |
- task_one->AllowToRun(); |
- task_two->AllowToRun(); |
- controller()->SetImageDecodeCache(nullptr); |
- |
- RunOrTimeout(&run_loop); |
- |
- EXPECT_TRUE(task_one->state().IsCanceled() || task_one->HasCompleted()); |
- EXPECT_TRUE(task_two->state().IsCanceled() || task_two->HasCompleted()); |
- EXPECT_EQ(expected_id1, decode_client1.id()); |
- EXPECT_EQ(expected_id2, decode_client2.id()); |
-} |
- |
-TEST_F(ImageControllerTest, QueueImageDecodeImageAlreadyLocked) { |
- scoped_refptr<SimpleTask> task(new SimpleTask); |
- cache()->SetTaskToUse(task); |
- |
- base::RunLoop run_loop1; |
- DecodeClient decode_client1; |
- ImageController::ImageDecodeRequestId expected_id1 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), |
- run_loop1.QuitClosure())); |
- RunOrTimeout(&run_loop1); |
- EXPECT_EQ(expected_id1, decode_client1.id()); |
- EXPECT_TRUE(task->has_run()); |
- |
- cache()->SetTaskToUse(nullptr); |
- base::RunLoop run_loop2; |
- DecodeClient decode_client2; |
- ImageController::ImageDecodeRequestId expected_id2 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client2), |
- run_loop2.QuitClosure())); |
- RunOrTimeout(&run_loop2); |
- EXPECT_EQ(expected_id2, decode_client2.id()); |
-} |
- |
-TEST_F(ImageControllerTest, QueueImageDecodeLockedImageControllerChange) { |
- scoped_refptr<SimpleTask> task(new SimpleTask); |
- cache()->SetTaskToUse(task); |
- |
- base::RunLoop run_loop1; |
- DecodeClient decode_client1; |
- ImageController::ImageDecodeRequestId expected_id1 = |
- controller()->QueueImageDecode( |
- image(), |
- base::Bind(&DecodeClient::Callback, base::Unretained(&decode_client1), |
- run_loop1.QuitClosure())); |
- RunOrTimeout(&run_loop1); |
- EXPECT_EQ(expected_id1, decode_client1.id()); |
- EXPECT_TRUE(task->has_run()); |
- EXPECT_EQ(1, cache()->number_of_refs()); |
- |
- controller()->SetImageDecodeCache(nullptr); |
- EXPECT_EQ(0, cache()->number_of_refs()); |
-} |
- |
-} // namespace |
} // namespace cc |