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

Side by Side Diff: cc/base/worker_pool_unittest.cc

Issue 14689004: Re-land: cc: Cancel and re-prioritize worker pool tasks. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Check and prevent worker pool reentrancy during dispatch of completion callbacks Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « cc/base/worker_pool_perftest.cc ('k') | cc/cc_tests.gyp » ('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 (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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 "cc/base/worker_pool.h" 5 #include "cc/base/worker_pool.h"
6 6
7 #include <vector>
8
9 #include "cc/base/completion_event.h"
7 #include "testing/gtest/include/gtest/gtest.h" 10 #include "testing/gtest/include/gtest/gtest.h"
8 11
9 namespace cc { 12 namespace cc {
10 13
11 namespace { 14 namespace {
12 15
16 class FakeTaskImpl : public internal::WorkerPoolTask {
17 public:
18 FakeTaskImpl(const base::Closure& callback,
19 const base::Closure& reply,
20 internal::WorkerPoolTask::TaskVector* dependencies)
21 : internal::WorkerPoolTask(dependencies),
22 callback_(callback),
23 reply_(reply) {
24 }
25 FakeTaskImpl(const base::Closure& callback, const base::Closure& reply)
26 : callback_(callback),
27 reply_(reply) {
28 }
29
30 // Overridden from internal::WorkerPoolTask:
31 virtual void RunOnThread(unsigned thread_index) OVERRIDE {
32 if (!callback_.is_null())
33 callback_.Run();
34 }
35 virtual void DispatchCompletionCallback() OVERRIDE {
36 if (!reply_.is_null())
37 reply_.Run();
38 }
39
40 private:
41 virtual ~FakeTaskImpl() {}
42
43 const base::Closure callback_;
44 const base::Closure reply_;
45 };
46
47 class FakeWorkerPool : public WorkerPool {
48 public:
49 FakeWorkerPool() : WorkerPool(1, base::TimeDelta::FromDays(1024), "test") {}
50 virtual ~FakeWorkerPool() {}
51
52 static scoped_ptr<FakeWorkerPool> Create() {
53 return make_scoped_ptr(new FakeWorkerPool);
54 }
55
56 void ScheduleTasks(const base::Closure& callback,
57 const base::Closure& reply,
58 const base::Closure& dependency,
59 int count) {
60 scoped_refptr<FakeTaskImpl> dependency_task(
61 new FakeTaskImpl(dependency, base::Closure()));
62
63 internal::WorkerPoolTask::TaskVector tasks;
64 for (int i = 0; i < count; ++i) {
65 internal::WorkerPoolTask::TaskVector dependencies(1, dependency_task);
66 tasks.push_back(new FakeTaskImpl(callback, reply, &dependencies));
67 }
68 scoped_refptr<FakeTaskImpl> completion_task(
69 new FakeTaskImpl(base::Bind(&FakeWorkerPool::OnTasksCompleted,
70 base::Unretained(this)),
71 base::Closure(),
72 &tasks));
73
74 scheduled_tasks_completion_.reset(new CompletionEvent);
75 WorkerPool::ScheduleTasks(completion_task);
76 }
77
78 void WaitForTasksToComplete() {
79 DCHECK(scheduled_tasks_completion_);
80 scheduled_tasks_completion_->Wait();
81 }
82
83 private:
84 void OnTasksCompleted() {
85 DCHECK(scheduled_tasks_completion_);
86 scheduled_tasks_completion_->Signal();
87 }
88
89 scoped_ptr<CompletionEvent> scheduled_tasks_completion_;
90 };
91
13 class WorkerPoolTest : public testing::Test, 92 class WorkerPoolTest : public testing::Test,
14 public WorkerPoolClient { 93 public WorkerPoolClient {
15 public: 94 public:
16 WorkerPoolTest() 95 WorkerPoolTest() : finish_dispatching_completion_callbacks_count_(0) {}
17 : run_task_count_(0), 96 virtual ~WorkerPoolTest() {}
18 on_task_completed_count_(0),
19 finish_dispatching_completion_callbacks_count_(0) {
20 }
21 virtual ~WorkerPoolTest() {
22 }
23 97
98 // Overridden from testing::Test:
24 virtual void SetUp() OVERRIDE { 99 virtual void SetUp() OVERRIDE {
25 Reset(); 100 Reset();
26 } 101 }
27
28 virtual void TearDown() OVERRIDE { 102 virtual void TearDown() OVERRIDE {
29 worker_pool_->Shutdown(); 103 worker_pool_->Shutdown();
30 } 104 }
31 105
32 // Overridden from WorkerPoolClient: 106 // Overridden from WorkerPoolClient:
33 virtual void DidFinishDispatchingWorkerPoolCompletionCallbacks() OVERRIDE { 107 virtual void DidFinishDispatchingWorkerPoolCompletionCallbacks() OVERRIDE {
34 ++finish_dispatching_completion_callbacks_count_; 108 ++finish_dispatching_completion_callbacks_count_;
35 } 109 }
36 110
37 void Reset() { 111 void Reset() {
38 worker_pool_ = WorkerPool::Create(1, 112 worker_pool_ = FakeWorkerPool::Create();
39 base::TimeDelta::FromDays(1024),
40 "test");
41 worker_pool_->SetClient(this); 113 worker_pool_->SetClient(this);
42 } 114 }
43 115
44 void RunAllTasksAndReset() { 116 void RunAllTasksAndReset() {
117 worker_pool_->WaitForTasksToComplete();
45 worker_pool_->Shutdown(); 118 worker_pool_->Shutdown();
46 Reset(); 119 Reset();
47 } 120 }
48 121
49 WorkerPool* worker_pool() { 122 FakeWorkerPool* worker_pool() {
50 return worker_pool_.get(); 123 return worker_pool_.get();
51 } 124 }
52 125
53 void RunTask() { 126 void RunTask(unsigned id) {
54 ++run_task_count_; 127 run_task_ids_.push_back(id);
55 } 128 }
56 129
57 void OnTaskCompleted() { 130 void OnTaskCompleted(unsigned id) {
58 ++on_task_completed_count_; 131 on_task_completed_ids_.push_back(id);
59 } 132 }
60 133
61 unsigned run_task_count() { 134 const std::vector<unsigned>& run_task_ids() {
62 return run_task_count_; 135 return run_task_ids_;
63 } 136 }
64 137
65 unsigned on_task_completed_count() { 138 const std::vector<unsigned>& on_task_completed_ids() {
66 return on_task_completed_count_; 139 return on_task_completed_ids_;
67 } 140 }
68 141
69 unsigned finish_dispatching_completion_callbacks_count() { 142 unsigned finish_dispatching_completion_callbacks_count() {
70 return finish_dispatching_completion_callbacks_count_; 143 return finish_dispatching_completion_callbacks_count_;
71 } 144 }
72 145
73 private: 146 private:
74 scoped_ptr<WorkerPool> worker_pool_; 147 scoped_ptr<FakeWorkerPool> worker_pool_;
75 unsigned run_task_count_; 148 std::vector<unsigned> run_task_ids_;
76 unsigned on_task_completed_count_; 149 std::vector<unsigned> on_task_completed_ids_;
77 unsigned finish_dispatching_completion_callbacks_count_; 150 unsigned finish_dispatching_completion_callbacks_count_;
78 }; 151 };
79 152
80 TEST_F(WorkerPoolTest, Basic) { 153 TEST_F(WorkerPoolTest, Basic) {
81 EXPECT_EQ(0u, run_task_count()); 154 EXPECT_EQ(0u, run_task_ids().size());
82 EXPECT_EQ(0u, on_task_completed_count()); 155 EXPECT_EQ(0u, on_task_completed_ids().size());
83 EXPECT_EQ(0u, finish_dispatching_completion_callbacks_count()); 156 EXPECT_EQ(0u, finish_dispatching_completion_callbacks_count());
84 157
85 worker_pool()->PostTaskAndReply( 158 worker_pool()->ScheduleTasks(
86 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this)), 159 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u),
87 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this))); 160 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 0u),
161 base::Closure(),
162 1);
88 RunAllTasksAndReset(); 163 RunAllTasksAndReset();
89 164
90 EXPECT_EQ(1u, run_task_count()); 165 EXPECT_EQ(1u, run_task_ids().size());
91 EXPECT_EQ(1u, on_task_completed_count()); 166 EXPECT_EQ(1u, on_task_completed_ids().size());
92 EXPECT_EQ(1u, finish_dispatching_completion_callbacks_count()); 167 EXPECT_EQ(1u, finish_dispatching_completion_callbacks_count());
93 168
94 worker_pool()->PostTaskAndReply( 169 worker_pool()->ScheduleTasks(
95 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this)), 170 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u),
96 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this))); 171 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 0u),
97 worker_pool()->PostTaskAndReply( 172 base::Closure(),
98 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this)), 173 2);
99 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this)));
100 RunAllTasksAndReset(); 174 RunAllTasksAndReset();
101 175
102 EXPECT_EQ(3u, run_task_count()); 176 EXPECT_EQ(3u, run_task_ids().size());
103 EXPECT_EQ(3u, on_task_completed_count()); 177 EXPECT_EQ(3u, on_task_completed_ids().size());
104 EXPECT_EQ(2u, finish_dispatching_completion_callbacks_count()); 178 EXPECT_EQ(2u, finish_dispatching_completion_callbacks_count());
105 } 179 }
106 180
181 TEST_F(WorkerPoolTest, Dependencies) {
182 worker_pool()->ScheduleTasks(
183 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 1u),
184 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 1u),
185 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u),
186 1);
187 RunAllTasksAndReset();
188
189 // Check if dependency ran before task.
190 ASSERT_EQ(2u, run_task_ids().size());
191 EXPECT_EQ(0u, run_task_ids()[0]);
192 EXPECT_EQ(1u, run_task_ids()[1]);
193 ASSERT_EQ(1u, on_task_completed_ids().size());
194 EXPECT_EQ(1u, on_task_completed_ids()[0]);
195
196 worker_pool()->ScheduleTasks(
197 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 1u),
198 base::Bind(&WorkerPoolTest::OnTaskCompleted, base::Unretained(this), 1u),
199 base::Bind(&WorkerPoolTest::RunTask, base::Unretained(this), 0u),
200 2);
201 RunAllTasksAndReset();
202
203 // Dependency should only run once.
204 ASSERT_EQ(5u, run_task_ids().size());
205 EXPECT_EQ(0u, run_task_ids()[2]);
206 EXPECT_EQ(1u, run_task_ids()[3]);
207 EXPECT_EQ(1u, run_task_ids()[4]);
208 ASSERT_EQ(3u, on_task_completed_ids().size());
209 EXPECT_EQ(1u, on_task_completed_ids()[1]);
210 EXPECT_EQ(1u, on_task_completed_ids()[2]);
211 }
212
107 } // namespace 213 } // namespace
108 214
109 } // namespace cc 215 } // namespace cc
OLDNEW
« no previous file with comments | « cc/base/worker_pool_perftest.cc ('k') | cc/cc_tests.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698