OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "base/deferred_sequenced_task_runner.h" | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/bind.h" | |
9 #include "base/bind_helpers.h" | |
10 #include "base/memory/ref_counted.h" | |
11 #include "base/message_loop.h" | |
12 #include "base/message_loop_proxy.h" | |
13 #include "base/threading/non_thread_safe.h" | |
14 #include "base/threading/thread.h" | |
15 #include "testing/gmock/include/gmock/gmock.h" | |
16 #include "testing/gtest/include/gtest/gtest.h" | |
17 | |
18 namespace { | |
19 | |
20 class DeferredSequencedTaskRunnerTest : public testing::Test, | |
21 public base::NonThreadSafe { | |
22 public: | |
23 class ExecuteTaskOnDestructor : | |
24 public base::RefCounted<ExecuteTaskOnDestructor> { | |
25 public: | |
26 ExecuteTaskOnDestructor( | |
27 DeferredSequencedTaskRunnerTest* executor, | |
28 int task_id) | |
29 : executor_(executor), | |
30 task_id_(task_id) { | |
31 } | |
32 private: | |
33 friend class base::RefCounted<ExecuteTaskOnDestructor>; | |
34 virtual ~ExecuteTaskOnDestructor() { | |
35 executor_->ExecuteTask(task_id_); | |
36 } | |
37 DeferredSequencedTaskRunnerTest* executor_; | |
38 int task_id_; | |
39 }; | |
40 | |
41 void ExecuteTask(int task_id) { | |
42 base::AutoLock lock(lock_); | |
43 executed_task_ids_.push_back(task_id); | |
44 } | |
45 | |
46 void PostExecuteTask(int task_id) { | |
47 runner_->PostTask(FROM_HERE, | |
48 base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask, | |
49 base::Unretained(this), | |
50 task_id)); | |
51 } | |
52 | |
53 void StartRunner() { | |
54 runner_->Start(); | |
55 } | |
56 | |
57 void DoNothing(ExecuteTaskOnDestructor* object) { | |
58 } | |
59 | |
60 protected: | |
61 DeferredSequencedTaskRunnerTest() : | |
62 loop_(), | |
63 runner_( | |
64 new base::DeferredSequencedTaskRunner(loop_.message_loop_proxy())) { | |
65 } | |
66 | |
67 MessageLoop loop_; | |
68 scoped_refptr<base::DeferredSequencedTaskRunner> runner_; | |
69 mutable base::Lock lock_; | |
70 std::vector<int> executed_task_ids_; | |
71 }; | |
72 | |
73 TEST_F(DeferredSequencedTaskRunnerTest, Stopped) { | |
74 runner_->PostTask(FROM_HERE, | |
75 base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask, | |
erikwright (departed)
2013/04/15 17:56:25
I'd consider wrapping the bind into a member metho
| |
76 base::Unretained(this), | |
77 1)); | |
78 loop_.RunUntilIdle(); | |
79 EXPECT_THAT(executed_task_ids_, testing::ElementsAre()); | |
80 } | |
81 | |
82 TEST_F(DeferredSequencedTaskRunnerTest, Start) { | |
83 runner_->Start(); | |
84 runner_->PostTask(FROM_HERE, | |
85 base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask, | |
86 base::Unretained(this), | |
87 1)); | |
88 loop_.RunUntilIdle(); | |
89 EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1)); | |
90 } | |
91 | |
92 TEST_F(DeferredSequencedTaskRunnerTest, StartWithMultipleElements) { | |
93 runner_->Start(); | |
94 for (int i = 1; i < 5; ++i) { | |
95 runner_->PostTask(FROM_HERE, | |
96 base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask, | |
97 base::Unretained(this), | |
98 i)); | |
99 } | |
100 loop_.RunUntilIdle(); | |
101 EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4)); | |
102 } | |
103 | |
104 TEST_F(DeferredSequencedTaskRunnerTest, DeferredStart) { | |
105 runner_->PostTask(FROM_HERE, | |
106 base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask, | |
107 base::Unretained(this), | |
108 1)); | |
109 loop_.RunUntilIdle(); | |
110 EXPECT_THAT(executed_task_ids_, testing::ElementsAre()); | |
111 | |
112 runner_->Start(); | |
113 loop_.RunUntilIdle(); | |
114 EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1)); | |
115 | |
116 runner_->PostTask(FROM_HERE, | |
117 base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask, | |
118 base::Unretained(this), | |
119 2)); | |
120 loop_.RunUntilIdle(); | |
121 EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2)); | |
122 } | |
123 | |
124 TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleElements) { | |
125 for (int i = 1; i < 5; ++i) { | |
126 runner_->PostTask(FROM_HERE, | |
127 base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask, | |
128 base::Unretained(this), | |
129 i)); | |
130 } | |
131 loop_.RunUntilIdle(); | |
132 EXPECT_THAT(executed_task_ids_, testing::ElementsAre()); | |
133 | |
134 runner_->Start(); | |
135 | |
136 for (int i = 5; i < 9; ++i) { | |
137 runner_->PostTask(FROM_HERE, | |
138 base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask, | |
139 base::Unretained(this), | |
140 i)); | |
141 } | |
142 loop_.RunUntilIdle(); | |
143 EXPECT_THAT(executed_task_ids_, testing::ElementsAre(1, 2, 3, 4, 5, 6, 7, 8)); | |
144 } | |
145 | |
146 TEST_F(DeferredSequencedTaskRunnerTest, DeferredStartWithMultipleThreads) { | |
147 { | |
148 base::Thread thread1("DeferredSequencedTaskRunnerTestThread1"); | |
149 base::Thread thread2("DeferredSequencedTaskRunnerTestThread2"); | |
150 thread1.Start(); | |
151 thread2.Start(); | |
152 for (int i = 0; i < 5; ++i) { | |
153 thread1.message_loop()->PostTask(FROM_HERE, | |
willchan no longer on Chromium
2013/04/16 01:03:04
Indentation is off here. All the parameters should
msarda
2013/04/17 09:53:55
Done.
| |
154 base::Bind(&DeferredSequencedTaskRunnerTest::PostExecuteTask, | |
155 base::Unretained(this), | |
156 2 * i)); | |
157 thread2.message_loop()->PostTask(FROM_HERE, | |
158 base::Bind(&DeferredSequencedTaskRunnerTest::PostExecuteTask, | |
159 base::Unretained(this), | |
160 2 * i + 1)); | |
161 if (i == 2) { | |
162 thread1.message_loop()->PostTask(FROM_HERE, | |
163 base::Bind(&DeferredSequencedTaskRunnerTest::StartRunner, | |
164 base::Unretained(this))); | |
165 } | |
166 } | |
167 } | |
168 | |
169 loop_.RunUntilIdle(); | |
170 EXPECT_THAT(executed_task_ids_, | |
171 testing::WhenSorted(testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9))); | |
172 } | |
173 | |
174 TEST_F(DeferredSequencedTaskRunnerTest, ObjectDestructionOrder) { | |
175 { | |
176 base::Thread thread("DeferredSequencedTaskRunnerTestThread"); | |
177 thread.Start(); | |
178 runner_ = | |
179 new base::DeferredSequencedTaskRunner(thread.message_loop_proxy()); | |
180 for (int i = 0; i < 5; ++i) { | |
181 { | |
182 // Use a block to ensure that no reference to |short_lived_object| | |
183 // is kept on the main thread after it is posted to |runner_|. | |
184 scoped_refptr<ExecuteTaskOnDestructor> short_lived_object = | |
185 new ExecuteTaskOnDestructor(this, 2 * i); | |
186 runner_->PostTask(FROM_HERE, | |
willchan no longer on Chromium
2013/04/16 01:03:04
Ditto here on parameter alignment.
msarda
2013/04/17 09:53:55
Done.
| |
187 base::Bind(&DeferredSequencedTaskRunnerTest::DoNothing, | |
188 base::Unretained(this), | |
189 short_lived_object)); | |
190 } | |
191 // |short_lived_object| with id |2 * i| should be destroyed before the | |
192 // task |2 * i + 1| is executed. | |
193 runner_->PostTask(FROM_HERE, | |
194 base::Bind(&DeferredSequencedTaskRunnerTest::ExecuteTask, | |
195 base::Unretained(this), | |
196 2 * i + 1)); | |
197 } | |
198 runner_->Start(); | |
199 } | |
200 | |
201 // All |short_lived_object| with id |2 * i| are destroyed before the task | |
202 // |2 * i + 1| is executed. | |
203 EXPECT_THAT(executed_task_ids_, | |
204 testing::ElementsAre(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)); | |
205 } | |
206 | |
207 } // namespace | |
OLD | NEW |