OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/message_loop/message_loop_proxy.h" | 5 #include "base/message_loop/message_loop_task_runner.h" |
6 | 6 |
7 #include "base/atomic_sequence_num.h" | 7 #include "base/atomic_sequence_num.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/debug/leak_annotations.h" | 9 #include "base/debug/leak_annotations.h" |
10 #include "base/memory/ref_counted.h" | |
11 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
12 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/message_loop/message_loop_task_runner.h" |
13 #include "base/synchronization/waitable_event.h" | 13 #include "base/synchronization/waitable_event.h" |
| 14 #include "base/thread_task_runner_handle.h" |
14 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "testing/platform_test.h" |
16 | 18 |
17 namespace base { | 19 namespace base { |
18 | 20 |
19 namespace { | 21 class MessageLoopTaskRunnerTest : public testing::Test { |
20 | |
21 class MessageLoopProxyTest : public testing::Test { | |
22 public: | 22 public: |
23 MessageLoopProxyTest() | 23 MessageLoopTaskRunnerTest() |
24 : current_loop_(new MessageLoop()), | 24 : current_loop_(new MessageLoop()), |
25 task_thread_("task_thread"), | 25 task_thread_("task_thread"), |
26 thread_sync_(true, false) { | 26 thread_sync_(true, false) {} |
27 } | |
28 | 27 |
29 void DeleteCurrentMessageLoop() { | 28 void DeleteCurrentMessageLoop() { current_loop_.reset(); } |
30 current_loop_.reset(); | |
31 } | |
32 | 29 |
33 protected: | 30 protected: |
34 void SetUp() override { | 31 void SetUp() override { |
35 // Use SetUp() instead of the constructor to avoid posting a task to a | 32 // Use SetUp() instead of the constructor to avoid posting a task to a |
36 // partialy constructed object. | 33 // partialy constructed object. |
37 task_thread_.Start(); | 34 task_thread_.Start(); |
38 | 35 |
39 // Allow us to pause the |task_thread_|'s MessageLoop. | 36 // Allow us to pause the |task_thread_|'s MessageLoop. |
40 task_thread_.message_loop()->PostTask( | 37 task_thread_.message_loop()->PostTask( |
41 FROM_HERE, | 38 FROM_HERE, Bind(&MessageLoopTaskRunnerTest::BlockTaskThreadHelper, |
42 Bind(&MessageLoopProxyTest::BlockTaskThreadHelper, Unretained(this))); | 39 Unretained(this))); |
43 } | 40 } |
44 | 41 |
45 void TearDown() override { | 42 void TearDown() override { |
46 // Make sure the |task_thread_| is not blocked, and stop the thread | 43 // Make sure the |task_thread_| is not blocked, and stop the thread |
47 // fully before destuction because its tasks may still depend on the | 44 // fully before destuction because its tasks may still depend on the |
48 // |thread_sync_| event. | 45 // |thread_sync_| event. |
49 thread_sync_.Signal(); | 46 thread_sync_.Signal(); |
50 task_thread_.Stop(); | 47 task_thread_.Stop(); |
51 DeleteCurrentMessageLoop(); | 48 DeleteCurrentMessageLoop(); |
52 } | 49 } |
53 | 50 |
54 // Make LoopRecorder threadsafe so that there is defined behavior even if a | 51 // Make LoopRecorder threadsafe so that there is defined behavior even if a |
55 // threading mistake sneaks into the PostTaskAndReplyRelay implementation. | 52 // threading mistake sneaks into the PostTaskAndReplyRelay implementation. |
56 class LoopRecorder : public RefCountedThreadSafe<LoopRecorder> { | 53 class LoopRecorder : public RefCountedThreadSafe<LoopRecorder> { |
57 public: | 54 public: |
58 LoopRecorder(MessageLoop** run_on, MessageLoop** deleted_on, | 55 LoopRecorder(MessageLoop** run_on, |
| 56 MessageLoop** deleted_on, |
59 int* destruct_order) | 57 int* destruct_order) |
60 : run_on_(run_on), | 58 : run_on_(run_on), |
61 deleted_on_(deleted_on), | 59 deleted_on_(deleted_on), |
62 destruct_order_(destruct_order) { | 60 destruct_order_(destruct_order) {} |
63 } | |
64 | 61 |
65 void RecordRun() { | 62 void RecordRun() { *run_on_ = MessageLoop::current(); } |
66 *run_on_ = MessageLoop::current(); | |
67 } | |
68 | 63 |
69 private: | 64 private: |
70 friend class RefCountedThreadSafe<LoopRecorder>; | 65 friend class RefCountedThreadSafe<LoopRecorder>; |
71 ~LoopRecorder() { | 66 ~LoopRecorder() { |
72 *deleted_on_ = MessageLoop::current(); | 67 *deleted_on_ = MessageLoop::current(); |
73 *destruct_order_ = g_order.GetNext(); | 68 *destruct_order_ = g_order.GetNext(); |
74 } | 69 } |
75 | 70 |
76 MessageLoop** run_on_; | 71 MessageLoop** run_on_; |
77 MessageLoop** deleted_on_; | 72 MessageLoop** deleted_on_; |
78 int* destruct_order_; | 73 int* destruct_order_; |
79 }; | 74 }; |
80 | 75 |
81 static void RecordLoop(scoped_refptr<LoopRecorder> recorder) { | 76 static void RecordLoop(scoped_refptr<LoopRecorder> recorder) { |
82 recorder->RecordRun(); | 77 recorder->RecordRun(); |
83 } | 78 } |
84 | 79 |
85 static void RecordLoopAndQuit(scoped_refptr<LoopRecorder> recorder) { | 80 static void RecordLoopAndQuit(scoped_refptr<LoopRecorder> recorder) { |
86 recorder->RecordRun(); | 81 recorder->RecordRun(); |
87 MessageLoop::current()->QuitWhenIdle(); | 82 MessageLoop::current()->QuitWhenIdle(); |
88 } | 83 } |
89 | 84 |
90 void UnblockTaskThread() { | 85 void UnblockTaskThread() { thread_sync_.Signal(); } |
91 thread_sync_.Signal(); | |
92 } | |
93 | 86 |
94 void BlockTaskThreadHelper() { | 87 void BlockTaskThreadHelper() { thread_sync_.Wait(); } |
95 thread_sync_.Wait(); | |
96 } | |
97 | 88 |
98 static StaticAtomicSequenceNumber g_order; | 89 static StaticAtomicSequenceNumber g_order; |
99 | 90 |
100 scoped_ptr<MessageLoop> current_loop_; | 91 scoped_ptr<MessageLoop> current_loop_; |
101 Thread task_thread_; | 92 Thread task_thread_; |
102 | 93 |
103 private: | 94 private: |
104 base::WaitableEvent thread_sync_; | 95 base::WaitableEvent thread_sync_; |
105 }; | 96 }; |
106 | 97 |
107 StaticAtomicSequenceNumber MessageLoopProxyTest::g_order; | 98 StaticAtomicSequenceNumber MessageLoopTaskRunnerTest::g_order; |
108 | 99 |
109 TEST_F(MessageLoopProxyTest, PostTaskAndReply_Basic) { | 100 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_Basic) { |
110 MessageLoop* task_run_on = NULL; | 101 MessageLoop* task_run_on = NULL; |
111 MessageLoop* task_deleted_on = NULL; | 102 MessageLoop* task_deleted_on = NULL; |
112 int task_delete_order = -1; | 103 int task_delete_order = -1; |
113 MessageLoop* reply_run_on = NULL; | 104 MessageLoop* reply_run_on = NULL; |
114 MessageLoop* reply_deleted_on = NULL; | 105 MessageLoop* reply_deleted_on = NULL; |
115 int reply_delete_order = -1; | 106 int reply_delete_order = -1; |
116 | 107 |
117 scoped_refptr<LoopRecorder> task_recoder = | 108 scoped_refptr<LoopRecorder> task_recoder = |
118 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); | 109 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); |
119 scoped_refptr<LoopRecorder> reply_recoder = | 110 scoped_refptr<LoopRecorder> reply_recoder = |
120 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); | 111 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); |
121 | 112 |
122 ASSERT_TRUE(task_thread_.message_loop_proxy()->PostTaskAndReply( | 113 ASSERT_TRUE(task_thread_.task_runner()->PostTaskAndReply( |
123 FROM_HERE, | 114 FROM_HERE, Bind(&RecordLoop, task_recoder), |
124 Bind(&RecordLoop, task_recoder), | |
125 Bind(&RecordLoopAndQuit, reply_recoder))); | 115 Bind(&RecordLoopAndQuit, reply_recoder))); |
126 | 116 |
127 // Die if base::Bind doesn't retain a reference to the recorders. | 117 // Die if base::Bind doesn't retain a reference to the recorders. |
128 task_recoder = NULL; | 118 task_recoder = NULL; |
129 reply_recoder = NULL; | 119 reply_recoder = NULL; |
130 ASSERT_FALSE(task_deleted_on); | 120 ASSERT_FALSE(task_deleted_on); |
131 ASSERT_FALSE(reply_deleted_on); | 121 ASSERT_FALSE(reply_deleted_on); |
132 | 122 |
133 UnblockTaskThread(); | 123 UnblockTaskThread(); |
134 current_loop_->Run(); | 124 current_loop_->Run(); |
135 | 125 |
136 EXPECT_EQ(task_thread_.message_loop(), task_run_on); | 126 EXPECT_EQ(task_thread_.message_loop(), task_run_on); |
137 EXPECT_EQ(current_loop_.get(), task_deleted_on); | 127 EXPECT_EQ(current_loop_.get(), task_deleted_on); |
138 EXPECT_EQ(current_loop_.get(), reply_run_on); | 128 EXPECT_EQ(current_loop_.get(), reply_run_on); |
139 EXPECT_EQ(current_loop_.get(), reply_deleted_on); | 129 EXPECT_EQ(current_loop_.get(), reply_deleted_on); |
140 EXPECT_LT(task_delete_order, reply_delete_order); | 130 EXPECT_LT(task_delete_order, reply_delete_order); |
141 } | 131 } |
142 | 132 |
143 TEST_F(MessageLoopProxyTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) { | 133 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) { |
144 MessageLoop* task_run_on = NULL; | 134 MessageLoop* task_run_on = NULL; |
145 MessageLoop* task_deleted_on = NULL; | 135 MessageLoop* task_deleted_on = NULL; |
146 int task_delete_order = -1; | 136 int task_delete_order = -1; |
147 MessageLoop* reply_run_on = NULL; | 137 MessageLoop* reply_run_on = NULL; |
148 MessageLoop* reply_deleted_on = NULL; | 138 MessageLoop* reply_deleted_on = NULL; |
149 int reply_delete_order = -1; | 139 int reply_delete_order = -1; |
150 | 140 |
151 scoped_refptr<LoopRecorder> task_recoder = | 141 scoped_refptr<LoopRecorder> task_recoder = |
152 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); | 142 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); |
153 scoped_refptr<LoopRecorder> reply_recoder = | 143 scoped_refptr<LoopRecorder> reply_recoder = |
154 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); | 144 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); |
155 | 145 |
156 // Grab a MessageLoopProxy to a dead MessageLoop. | 146 // Grab a task runner to a dead MessageLoop. |
157 scoped_refptr<MessageLoopProxy> task_loop_proxy = | 147 scoped_refptr<SingleThreadTaskRunner> task_runner = |
158 task_thread_.message_loop_proxy(); | 148 task_thread_.task_runner(); |
159 UnblockTaskThread(); | 149 UnblockTaskThread(); |
160 task_thread_.Stop(); | 150 task_thread_.Stop(); |
161 | 151 |
162 ASSERT_FALSE(task_loop_proxy->PostTaskAndReply( | 152 ASSERT_FALSE( |
163 FROM_HERE, | 153 task_runner->PostTaskAndReply(FROM_HERE, Bind(&RecordLoop, task_recoder), |
164 Bind(&RecordLoop, task_recoder), | 154 Bind(&RecordLoopAndQuit, reply_recoder))); |
165 Bind(&RecordLoopAndQuit, reply_recoder))); | |
166 | 155 |
167 // The relay should have properly deleted its resources leaving us as the only | 156 // The relay should have properly deleted its resources leaving us as the only |
168 // reference. | 157 // reference. |
169 EXPECT_EQ(task_delete_order, reply_delete_order); | 158 EXPECT_EQ(task_delete_order, reply_delete_order); |
170 ASSERT_TRUE(task_recoder->HasOneRef()); | 159 ASSERT_TRUE(task_recoder->HasOneRef()); |
171 ASSERT_TRUE(reply_recoder->HasOneRef()); | 160 ASSERT_TRUE(reply_recoder->HasOneRef()); |
172 | 161 |
173 // Nothing should have run though. | 162 // Nothing should have run though. |
174 EXPECT_FALSE(task_run_on); | 163 EXPECT_FALSE(task_run_on); |
175 EXPECT_FALSE(reply_run_on); | 164 EXPECT_FALSE(reply_run_on); |
176 } | 165 } |
177 | 166 |
178 TEST_F(MessageLoopProxyTest, PostTaskAndReply_SameLoop) { | 167 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_SameLoop) { |
179 MessageLoop* task_run_on = NULL; | 168 MessageLoop* task_run_on = NULL; |
180 MessageLoop* task_deleted_on = NULL; | 169 MessageLoop* task_deleted_on = NULL; |
181 int task_delete_order = -1; | 170 int task_delete_order = -1; |
182 MessageLoop* reply_run_on = NULL; | 171 MessageLoop* reply_run_on = NULL; |
183 MessageLoop* reply_deleted_on = NULL; | 172 MessageLoop* reply_deleted_on = NULL; |
184 int reply_delete_order = -1; | 173 int reply_delete_order = -1; |
185 | 174 |
186 scoped_refptr<LoopRecorder> task_recoder = | 175 scoped_refptr<LoopRecorder> task_recoder = |
187 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); | 176 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); |
188 scoped_refptr<LoopRecorder> reply_recoder = | 177 scoped_refptr<LoopRecorder> reply_recoder = |
189 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); | 178 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); |
190 | 179 |
191 // Enqueue the relay. | 180 // Enqueue the relay. |
192 ASSERT_TRUE(current_loop_->message_loop_proxy()->PostTaskAndReply( | 181 ASSERT_TRUE(current_loop_->task_runner()->PostTaskAndReply( |
193 FROM_HERE, | 182 FROM_HERE, Bind(&RecordLoop, task_recoder), |
194 Bind(&RecordLoop, task_recoder), | |
195 Bind(&RecordLoopAndQuit, reply_recoder))); | 183 Bind(&RecordLoopAndQuit, reply_recoder))); |
196 | 184 |
197 // Die if base::Bind doesn't retain a reference to the recorders. | 185 // Die if base::Bind doesn't retain a reference to the recorders. |
198 task_recoder = NULL; | 186 task_recoder = NULL; |
199 reply_recoder = NULL; | 187 reply_recoder = NULL; |
200 ASSERT_FALSE(task_deleted_on); | 188 ASSERT_FALSE(task_deleted_on); |
201 ASSERT_FALSE(reply_deleted_on); | 189 ASSERT_FALSE(reply_deleted_on); |
202 | 190 |
203 current_loop_->Run(); | 191 current_loop_->Run(); |
204 | 192 |
205 EXPECT_EQ(current_loop_.get(), task_run_on); | 193 EXPECT_EQ(current_loop_.get(), task_run_on); |
206 EXPECT_EQ(current_loop_.get(), task_deleted_on); | 194 EXPECT_EQ(current_loop_.get(), task_deleted_on); |
207 EXPECT_EQ(current_loop_.get(), reply_run_on); | 195 EXPECT_EQ(current_loop_.get(), reply_run_on); |
208 EXPECT_EQ(current_loop_.get(), reply_deleted_on); | 196 EXPECT_EQ(current_loop_.get(), reply_deleted_on); |
209 EXPECT_LT(task_delete_order, reply_delete_order); | 197 EXPECT_LT(task_delete_order, reply_delete_order); |
210 } | 198 } |
211 | 199 |
212 TEST_F(MessageLoopProxyTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) { | 200 TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_DeadReplyLoopDoesNotDelete) { |
213 // Annotate the scope as having memory leaks to suppress heapchecker reports. | 201 // Annotate the scope as having memory leaks to suppress heapchecker reports. |
214 ANNOTATE_SCOPED_MEMORY_LEAK; | 202 ANNOTATE_SCOPED_MEMORY_LEAK; |
215 MessageLoop* task_run_on = NULL; | 203 MessageLoop* task_run_on = NULL; |
216 MessageLoop* task_deleted_on = NULL; | 204 MessageLoop* task_deleted_on = NULL; |
217 int task_delete_order = -1; | 205 int task_delete_order = -1; |
218 MessageLoop* reply_run_on = NULL; | 206 MessageLoop* reply_run_on = NULL; |
219 MessageLoop* reply_deleted_on = NULL; | 207 MessageLoop* reply_deleted_on = NULL; |
220 int reply_delete_order = -1; | 208 int reply_delete_order = -1; |
221 | 209 |
222 scoped_refptr<LoopRecorder> task_recoder = | 210 scoped_refptr<LoopRecorder> task_recoder = |
223 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); | 211 new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order); |
224 scoped_refptr<LoopRecorder> reply_recoder = | 212 scoped_refptr<LoopRecorder> reply_recoder = |
225 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); | 213 new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order); |
226 | 214 |
227 // Enqueue the relay. | 215 // Enqueue the relay. |
228 task_thread_.message_loop_proxy()->PostTaskAndReply( | 216 task_thread_.task_runner()->PostTaskAndReply( |
229 FROM_HERE, | 217 FROM_HERE, Bind(&RecordLoop, task_recoder), |
230 Bind(&RecordLoop, task_recoder), | |
231 Bind(&RecordLoopAndQuit, reply_recoder)); | 218 Bind(&RecordLoopAndQuit, reply_recoder)); |
232 | 219 |
233 // Die if base::Bind doesn't retain a reference to the recorders. | 220 // Die if base::Bind doesn't retain a reference to the recorders. |
234 task_recoder = NULL; | 221 task_recoder = NULL; |
235 reply_recoder = NULL; | 222 reply_recoder = NULL; |
236 ASSERT_FALSE(task_deleted_on); | 223 ASSERT_FALSE(task_deleted_on); |
237 ASSERT_FALSE(reply_deleted_on); | 224 ASSERT_FALSE(reply_deleted_on); |
238 | 225 |
239 UnblockTaskThread(); | 226 UnblockTaskThread(); |
240 | 227 |
(...skipping 13 matching lines...) Expand all Loading... |
254 EXPECT_EQ(task_delete_order, reply_delete_order); | 241 EXPECT_EQ(task_delete_order, reply_delete_order); |
255 | 242 |
256 // The PostTaskAndReplyRelay is leaked here. Even if we had a reference to | 243 // The PostTaskAndReplyRelay is leaked here. Even if we had a reference to |
257 // it, we cannot just delete it because PostTaskAndReplyRelay's destructor | 244 // it, we cannot just delete it because PostTaskAndReplyRelay's destructor |
258 // checks that MessageLoop::current() is the the same as when the | 245 // checks that MessageLoop::current() is the the same as when the |
259 // PostTaskAndReplyRelay object was constructed. However, this loop must have | 246 // PostTaskAndReplyRelay object was constructed. However, this loop must have |
260 // aleady been deleted in order to perform this test. See | 247 // aleady been deleted in order to perform this test. See |
261 // http://crbug.com/86301. | 248 // http://crbug.com/86301. |
262 } | 249 } |
263 | 250 |
264 } // namespace | 251 class MessageLoopTaskRunnerThreadingTest : public testing::Test { |
| 252 public: |
| 253 void Release() const { |
| 254 AssertOnIOThread(); |
| 255 Quit(); |
| 256 } |
| 257 |
| 258 void Quit() const { |
| 259 loop_.PostTask(FROM_HERE, MessageLoop::QuitWhenIdleClosure()); |
| 260 } |
| 261 |
| 262 void AssertOnIOThread() const { |
| 263 ASSERT_TRUE(io_thread_->task_runner()->BelongsToCurrentThread()); |
| 264 ASSERT_EQ(io_thread_->task_runner(), ThreadTaskRunnerHandle::Get()); |
| 265 } |
| 266 |
| 267 void AssertOnFileThread() const { |
| 268 ASSERT_TRUE(file_thread_->task_runner()->BelongsToCurrentThread()); |
| 269 ASSERT_EQ(file_thread_->task_runner(), ThreadTaskRunnerHandle::Get()); |
| 270 } |
| 271 |
| 272 protected: |
| 273 void SetUp() override { |
| 274 io_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_IO")); |
| 275 file_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_File")); |
| 276 io_thread_->Start(); |
| 277 file_thread_->Start(); |
| 278 } |
| 279 |
| 280 void TearDown() override { |
| 281 io_thread_->Stop(); |
| 282 file_thread_->Stop(); |
| 283 } |
| 284 |
| 285 static void BasicFunction(MessageLoopTaskRunnerThreadingTest* test) { |
| 286 test->AssertOnFileThread(); |
| 287 test->Quit(); |
| 288 } |
| 289 |
| 290 static void AssertNotRun() { FAIL() << "Callback Should not get executed."; } |
| 291 |
| 292 class DeletedOnFile { |
| 293 public: |
| 294 explicit DeletedOnFile(MessageLoopTaskRunnerThreadingTest* test) |
| 295 : test_(test) {} |
| 296 |
| 297 ~DeletedOnFile() { |
| 298 test_->AssertOnFileThread(); |
| 299 test_->Quit(); |
| 300 } |
| 301 |
| 302 private: |
| 303 MessageLoopTaskRunnerThreadingTest* test_; |
| 304 }; |
| 305 |
| 306 scoped_ptr<Thread> io_thread_; |
| 307 scoped_ptr<Thread> file_thread_; |
| 308 |
| 309 private: |
| 310 mutable MessageLoop loop_; |
| 311 }; |
| 312 |
| 313 TEST_F(MessageLoopTaskRunnerThreadingTest, Release) { |
| 314 EXPECT_TRUE(io_thread_->task_runner()->ReleaseSoon(FROM_HERE, this)); |
| 315 MessageLoop::current()->Run(); |
| 316 } |
| 317 |
| 318 TEST_F(MessageLoopTaskRunnerThreadingTest, Delete) { |
| 319 DeletedOnFile* deleted_on_file = new DeletedOnFile(this); |
| 320 EXPECT_TRUE( |
| 321 file_thread_->task_runner()->DeleteSoon(FROM_HERE, deleted_on_file)); |
| 322 MessageLoop::current()->Run(); |
| 323 } |
| 324 |
| 325 TEST_F(MessageLoopTaskRunnerThreadingTest, PostTask) { |
| 326 EXPECT_TRUE(file_thread_->task_runner()->PostTask( |
| 327 FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::BasicFunction, |
| 328 Unretained(this)))); |
| 329 MessageLoop::current()->Run(); |
| 330 } |
| 331 |
| 332 TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadExits) { |
| 333 scoped_ptr<Thread> test_thread( |
| 334 new Thread("MessageLoopTaskRunnerThreadingTest_Dummy")); |
| 335 test_thread->Start(); |
| 336 scoped_refptr<SingleThreadTaskRunner> task_runner = |
| 337 test_thread->task_runner(); |
| 338 test_thread->Stop(); |
| 339 |
| 340 bool ret = task_runner->PostTask( |
| 341 FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun)); |
| 342 EXPECT_FALSE(ret); |
| 343 } |
| 344 |
| 345 TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadIsDeleted) { |
| 346 scoped_refptr<SingleThreadTaskRunner> task_runner; |
| 347 { |
| 348 scoped_ptr<Thread> test_thread( |
| 349 new Thread("MessageLoopTaskRunnerThreadingTest_Dummy")); |
| 350 test_thread->Start(); |
| 351 task_runner = test_thread->task_runner(); |
| 352 } |
| 353 bool ret = task_runner->PostTask( |
| 354 FROM_HERE, Bind(&MessageLoopTaskRunnerThreadingTest::AssertNotRun)); |
| 355 EXPECT_FALSE(ret); |
| 356 } |
265 | 357 |
266 } // namespace base | 358 } // namespace base |
OLD | NEW |