| 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 |