OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/task.h" | |
6 | |
7 #include "base/bind.h" | |
5 #include "base/memory/ref_counted.h" | 8 #include "base/memory/ref_counted.h" |
6 #include "base/task.h" | 9 #include "base/message_loop.h" |
10 #include "base/threading/thread.h" | |
7 #include "testing/gtest/include/gtest/gtest.h" | 11 #include "testing/gtest/include/gtest/gtest.h" |
8 | 12 |
9 namespace { | 13 namespace { |
10 | 14 |
11 class CancelInDestructor : public base::RefCounted<CancelInDestructor> { | 15 class CancelInDestructor : public base::RefCounted<CancelInDestructor> { |
12 public: | 16 public: |
13 CancelInDestructor() : cancelable_task_(NULL) {} | 17 CancelInDestructor() : cancelable_task_(NULL) {} |
14 | 18 |
15 void Start() { | 19 void Start() { |
16 if (cancelable_task_) { | 20 if (cancelable_task_) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
100 EXPECT_EQ(0, run_count); | 104 EXPECT_EQ(0, run_count); |
101 done_task->Run(); | 105 done_task->Run(); |
102 EXPECT_FALSE(was_deleted); | 106 EXPECT_FALSE(was_deleted); |
103 EXPECT_EQ(1, run_count); | 107 EXPECT_EQ(1, run_count); |
104 } | 108 } |
105 EXPECT_EQ(1, run_count); | 109 EXPECT_EQ(1, run_count); |
106 delete done_task; | 110 delete done_task; |
107 EXPECT_TRUE(was_deleted); | 111 EXPECT_TRUE(was_deleted); |
108 } | 112 } |
109 | 113 |
114 class LoopRecorder : public base::RefCountedThreadSafe<LoopRecorder> { | |
willchan no longer on Chromium
2011/08/17 04:36:07
I'm not sure why you make this RefCountedThreadSaf
awong
2011/08/17 05:16:00
I figured that in the case that someone introduced
| |
115 public: | |
116 LoopRecorder(MessageLoop** run_on, MessageLoop** deleted_on) | |
117 : run_on_(run_on), | |
118 deleted_on_(deleted_on) { | |
119 } | |
120 | |
121 void RecordRun() { | |
122 *run_on_ = MessageLoop::current(); | |
123 } | |
124 | |
125 private: | |
126 friend class base::RefCountedThreadSafe<LoopRecorder>; | |
127 ~LoopRecorder() { | |
128 *deleted_on_ = MessageLoop::current(); | |
129 } | |
130 | |
131 MessageLoop** run_on_; | |
132 MessageLoop** deleted_on_; | |
133 }; | |
134 | |
135 void RecordLoop(scoped_refptr<LoopRecorder> recorder) { | |
136 recorder->RecordRun(); | |
137 } | |
138 | |
139 void RecordLoopAndQuit(scoped_refptr<LoopRecorder> recorder) { | |
140 recorder->RecordRun(); | |
141 MessageLoop::current()->Quit(); | |
142 } | |
143 | |
144 TEST(TaskTest, TestPostTaskAndReplyRelay_Basic) { | |
145 using base::internal::PostTaskAndReplyRelay; | |
146 | |
147 MessageLoop current_loop; | |
148 | |
149 MessageLoop* task_run_on = NULL; | |
150 MessageLoop* task_deleted_on = NULL; | |
151 MessageLoop* reply_run_on = NULL; | |
152 MessageLoop* reply_deleted_on = NULL; | |
153 | |
154 scoped_refptr<LoopRecorder> task_recoder = | |
willchan no longer on Chromium
2011/08/17 04:36:07
s/task_recoder/task_recorder/?
awong
2011/08/17 05:16:00
Will fix tomorrow.
| |
155 new LoopRecorder(&task_run_on, &task_deleted_on); | |
156 scoped_refptr<LoopRecorder> reply_recoder = | |
157 new LoopRecorder(&reply_run_on, &reply_deleted_on); | |
158 | |
159 PostTaskAndReplyRelay* relay = | |
160 new PostTaskAndReplyRelay( | |
161 FROM_HERE, | |
162 base::Bind(&RecordLoop, task_recoder), | |
163 base::Bind(&RecordLoopAndQuit, reply_recoder)); | |
164 | |
165 // Die if base::Bind doesn't retain a reference to the recorders. | |
166 task_recoder = NULL; | |
167 reply_recoder = NULL; | |
168 ASSERT_FALSE(task_deleted_on); | |
169 ASSERT_FALSE(reply_deleted_on); | |
170 | |
171 // Run the relay. | |
172 base::Thread task_thread("task_thread"); | |
173 task_thread.Start(); | |
174 task_thread.message_loop()->PostTask( | |
175 FROM_HERE, | |
176 base::Bind(&PostTaskAndReplyRelay::Run, base::Unretained(relay))); | |
177 | |
178 current_loop.Run(); | |
179 | |
180 EXPECT_EQ(task_thread.message_loop(), task_run_on); | |
181 EXPECT_EQ(¤t_loop, task_deleted_on); | |
182 EXPECT_EQ(¤t_loop, reply_run_on); | |
183 EXPECT_EQ(¤t_loop, reply_deleted_on); | |
184 } | |
185 | |
186 TEST(TaskTest, TestPostTaskAndReplyRelay_SameLoop) { | |
187 using base::internal::PostTaskAndReplyRelay; | |
188 | |
189 MessageLoop current_loop; | |
190 | |
191 MessageLoop* task_run_on = NULL; | |
192 MessageLoop* task_deleted_on = NULL; | |
193 MessageLoop* reply_run_on = NULL; | |
194 MessageLoop* reply_deleted_on = NULL; | |
195 | |
196 scoped_refptr<LoopRecorder> task_recoder = | |
197 new LoopRecorder(&task_run_on, &task_deleted_on); | |
198 scoped_refptr<LoopRecorder> reply_recoder = | |
199 new LoopRecorder(&reply_run_on, &reply_deleted_on); | |
200 | |
201 PostTaskAndReplyRelay* relay = | |
202 new PostTaskAndReplyRelay( | |
203 FROM_HERE, | |
204 base::Bind(&RecordLoop, task_recoder), | |
205 base::Bind(&RecordLoopAndQuit, reply_recoder)); | |
206 | |
207 // Die if base::Bind doesn't retain a reference to the recorders. | |
208 task_recoder = NULL; | |
209 reply_recoder = NULL; | |
210 ASSERT_FALSE(task_deleted_on); | |
211 ASSERT_FALSE(reply_deleted_on); | |
212 | |
213 // Run the relay. | |
214 current_loop.PostTask( | |
215 FROM_HERE, | |
216 base::Bind(&PostTaskAndReplyRelay::Run, base::Unretained(relay))); | |
217 | |
218 current_loop.Run(); | |
219 | |
220 EXPECT_EQ(¤t_loop, task_run_on); | |
221 EXPECT_EQ(¤t_loop, task_deleted_on); | |
222 EXPECT_EQ(¤t_loop, reply_run_on); | |
223 EXPECT_EQ(¤t_loop, reply_deleted_on); | |
224 } | |
225 | |
226 TEST(TaskTest, TestPostTaskAndReplyRelay_DeadReplyLoopDoesNotDelete) { | |
227 using base::internal::PostTaskAndReplyRelay; | |
228 | |
229 scoped_ptr<MessageLoop> current_loop(new MessageLoop()); | |
230 | |
231 MessageLoop* task_run_on = NULL; | |
232 MessageLoop* task_deleted_on = NULL; | |
233 MessageLoop* reply_run_on = NULL; | |
234 MessageLoop* reply_deleted_on = NULL; | |
235 | |
236 scoped_refptr<LoopRecorder> task_recoder = | |
237 new LoopRecorder(&task_run_on, &task_deleted_on); | |
238 scoped_refptr<LoopRecorder> reply_recoder = | |
239 new LoopRecorder(&reply_run_on, &reply_deleted_on); | |
240 | |
241 PostTaskAndReplyRelay* relay = | |
242 new PostTaskAndReplyRelay( | |
243 FROM_HERE, | |
244 base::Bind(&RecordLoop, task_recoder), | |
245 base::Bind(&RecordLoopAndQuit, reply_recoder)); | |
246 | |
247 // Die if base::Bind doesn't retain a reference to the recorders. | |
248 task_recoder = NULL; | |
249 reply_recoder = NULL; | |
250 ASSERT_FALSE(task_deleted_on); | |
251 ASSERT_FALSE(reply_deleted_on); | |
252 | |
253 // Run the relay. | |
254 base::Thread task_thread("task_thread"); | |
255 task_thread.Start(); | |
256 task_thread.message_loop()->PostTask( | |
257 FROM_HERE, | |
258 base::Bind(&PostTaskAndReplyRelay::Run, base::Unretained(relay))); | |
259 | |
260 // Mercilessly whack the current loop before |reply| gets to run. | |
261 current_loop.reset(); | |
262 | |
263 // This should ensure the relay has been run. We need to record the | |
264 // MessageLoop pointer before stopping the thread because Thread::Stop() will | |
265 // NULL out its own pointer. | |
266 MessageLoop* task_loop = task_thread.message_loop(); | |
267 task_thread.Stop(); | |
268 | |
269 EXPECT_EQ(task_loop, task_run_on); | |
270 ASSERT_FALSE(task_deleted_on); | |
271 EXPECT_FALSE(reply_run_on); | |
272 ASSERT_FALSE(reply_deleted_on); | |
273 | |
274 // Relay is leaked here. | |
275 // TODO(ajwong): Is there a way to make Valgrind not hate us? | |
willchan no longer on Chromium
2011/08/17 04:36:07
delete relay; :)
awong
2011/08/17 05:16:00
Tried that. Dies cause the Relay asserts that it i
| |
276 } | |
277 | |
110 } // namespace | 278 } // namespace |
OLD | NEW |