| 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 <vector> | 5 #include <vector> |
| 6 | 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" |
| 9 #include "base/compiler_specific.h" |
| 7 #include "base/eintr_wrapper.h" | 10 #include "base/eintr_wrapper.h" |
| 8 #include "base/logging.h" | 11 #include "base/logging.h" |
| 9 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 10 #include "base/ref_counted.h" | 13 #include "base/ref_counted.h" |
| 11 #include "base/task.h" | |
| 12 #include "base/threading/platform_thread.h" | 14 #include "base/threading/platform_thread.h" |
| 13 #include "base/threading/thread.h" | 15 #include "base/threading/thread.h" |
| 14 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 15 | 17 |
| 16 #if defined(OS_WIN) | 18 #if defined(OS_WIN) |
| 17 #include "base/message_pump_win.h" | 19 #include "base/message_pump_win.h" |
| 18 #include "base/win/scoped_handle.h" | 20 #include "base/win/scoped_handle.h" |
| 19 #endif | 21 #endif |
| 20 #if defined(OS_POSIX) | 22 #if defined(OS_POSIX) |
| 21 #include "base/message_pump_libevent.h" | 23 #include "base/message_pump_libevent.h" |
| 22 #endif | 24 #endif |
| 23 | 25 |
| 24 using base::PlatformThread; | 26 using base::PlatformThread; |
| 25 using base::Thread; | 27 using base::Thread; |
| 26 using base::Time; | 28 using base::Time; |
| 27 using base::TimeDelta; | 29 using base::TimeDelta; |
| 30 using base::TimeTicks; |
| 28 | 31 |
| 29 // TODO(darin): Platform-specific MessageLoop tests should be grouped together | 32 // TODO(darin): Platform-specific MessageLoop tests should be grouped together |
| 30 // to avoid chopping this file up with so many #ifdefs. | 33 // to avoid chopping this file up with so many #ifdefs. |
| 31 | 34 |
| 32 namespace { | 35 namespace { |
| 33 | 36 |
| 34 class MessageLoopTest : public testing::Test {}; | 37 class MessageLoopTest : public testing::Test {}; |
| 35 | 38 |
| 36 class Foo : public base::RefCounted<Foo> { | 39 class Foo : public base::RefCounted<Foo> { |
| 37 public: | 40 public: |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 | 76 |
| 74 private: | 77 private: |
| 75 friend class base::RefCounted<Foo>; | 78 friend class base::RefCounted<Foo>; |
| 76 | 79 |
| 77 ~Foo() {} | 80 ~Foo() {} |
| 78 | 81 |
| 79 int test_count_; | 82 int test_count_; |
| 80 std::string result_; | 83 std::string result_; |
| 81 }; | 84 }; |
| 82 | 85 |
| 83 class QuitMsgLoop : public base::RefCounted<QuitMsgLoop> { | 86 // TODO(ajwong): Remove this once we've finished getting rid of the PostTask() |
| 84 public: | 87 // compatibility methods. |
| 85 void QuitNow() { | |
| 86 MessageLoop::current()->Quit(); | |
| 87 } | |
| 88 | |
| 89 private: | |
| 90 friend class base::RefCounted<QuitMsgLoop>; | |
| 91 | |
| 92 ~QuitMsgLoop() {} | |
| 93 }; | |
| 94 | |
| 95 void RunTest_PostTask(MessageLoop::Type message_loop_type) { | 88 void RunTest_PostTask(MessageLoop::Type message_loop_type) { |
| 96 MessageLoop loop(message_loop_type); | 89 MessageLoop loop(message_loop_type); |
| 97 | 90 |
| 98 // Add tests to message loop | 91 // Add tests to message loop |
| 99 scoped_refptr<Foo> foo(new Foo()); | 92 scoped_refptr<Foo> foo(new Foo()); |
| 100 std::string a("a"), b("b"), c("c"), d("d"); | 93 std::string a("a"), b("b"), c("c"), d("d"); |
| 101 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 94 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 102 foo.get(), &Foo::Test0)); | 95 foo.get(), &Foo::Test0)); |
| 103 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 96 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 104 foo.get(), &Foo::Test1ConstRef, a)); | 97 foo.get(), &Foo::Test1ConstRef, a)); |
| 105 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 98 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 106 foo.get(), &Foo::Test1Ptr, &b)); | 99 foo.get(), &Foo::Test1Ptr, &b)); |
| 107 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 100 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 108 foo.get(), &Foo::Test1Int, 100)); | 101 foo.get(), &Foo::Test1Int, 100)); |
| 109 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 102 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 110 foo.get(), &Foo::Test2Ptr, &a, &c)); | 103 foo.get(), &Foo::Test2Ptr, &a, &c)); |
| 111 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 104 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 112 foo.get(), &Foo::Test2Mixed, a, &d)); | 105 foo.get(), &Foo::Test2Mixed, a, &d)); |
| 113 | 106 |
| 114 // After all tests, post a message that will shut down the message loop | 107 // After all tests, post a message that will shut down the message loop |
| 115 scoped_refptr<QuitMsgLoop> quit(new QuitMsgLoop()); | 108 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 116 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 109 &MessageLoop::Quit, base::Unretained(MessageLoop::current()))); |
| 117 quit.get(), &QuitMsgLoop::QuitNow)); | |
| 118 | 110 |
| 119 // Now kick things off | 111 // Now kick things off |
| 120 MessageLoop::current()->Run(); | 112 MessageLoop::current()->Run(); |
| 121 | 113 |
| 122 EXPECT_EQ(foo->test_count(), 105); | 114 EXPECT_EQ(foo->test_count(), 105); |
| 123 EXPECT_EQ(foo->result(), "abacad"); | 115 EXPECT_EQ(foo->result(), "abacad"); |
| 124 } | 116 } |
| 125 | 117 |
| 126 void RunTest_PostTask_SEH(MessageLoop::Type message_loop_type) { | 118 void RunTest_PostClosure(MessageLoop::Type message_loop_type) { |
| 127 MessageLoop loop(message_loop_type); | 119 MessageLoop loop(message_loop_type); |
| 128 | 120 |
| 129 // Add tests to message loop | 121 // Add tests to message loop |
| 130 scoped_refptr<Foo> foo(new Foo()); | 122 scoped_refptr<Foo> foo(new Foo()); |
| 131 std::string a("a"), b("b"), c("c"), d("d"); | 123 std::string a("a"), b("b"), c("c"), d("d"); |
| 132 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 124 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 133 foo.get(), &Foo::Test0)); | 125 &Foo::Test0, foo.get())); |
| 134 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 126 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 135 foo.get(), &Foo::Test1ConstRef, a)); | 127 &Foo::Test1ConstRef, foo.get(), a)); |
| 136 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 128 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 137 foo.get(), &Foo::Test1Ptr, &b)); | 129 &Foo::Test1Ptr, foo.get(), &b)); |
| 138 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 130 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 139 foo.get(), &Foo::Test1Int, 100)); | 131 &Foo::Test1Int, foo.get(), 100)); |
| 140 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 132 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 141 foo.get(), &Foo::Test2Ptr, &a, &c)); | 133 &Foo::Test2Ptr, foo.get(), &a, &c)); |
| 142 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 134 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 143 foo.get(), &Foo::Test2Mixed, a, &d)); | 135 &Foo::Test2Mixed, foo.get(), a, &d)); |
| 144 | 136 |
| 145 // After all tests, post a message that will shut down the message loop | 137 // After all tests, post a message that will shut down the message loop |
| 146 scoped_refptr<QuitMsgLoop> quit(new QuitMsgLoop()); | 138 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 147 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 139 &MessageLoop::Quit, base::Unretained(MessageLoop::current()))); |
| 148 quit.get(), &QuitMsgLoop::QuitNow)); | 140 |
| 141 // Now kick things off |
| 142 MessageLoop::current()->Run(); |
| 143 |
| 144 EXPECT_EQ(foo->test_count(), 105); |
| 145 EXPECT_EQ(foo->result(), "abacad"); |
| 146 } |
| 147 |
| 148 void RunTest_PostClosure_SEH(MessageLoop::Type message_loop_type) { |
| 149 MessageLoop loop(message_loop_type); |
| 150 |
| 151 // Add tests to message loop |
| 152 scoped_refptr<Foo> foo(new Foo()); |
| 153 std::string a("a"), b("b"), c("c"), d("d"); |
| 154 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 155 &Foo::Test0, foo.get())); |
| 156 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 157 &Foo::Test1ConstRef,foo.get(), a)); |
| 158 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 159 &Foo::Test1Ptr,foo.get(), &b)); |
| 160 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 161 &Foo::Test1Int,foo.get(), 100)); |
| 162 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 163 &Foo::Test2Ptr,foo.get(), &a, &c)); |
| 164 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 165 &Foo::Test2Mixed,foo.get(), a, &d)); |
| 166 |
| 167 // After all tests, post a message that will shut down the message loop |
| 168 MessageLoop::current()->PostClosure(FROM_HERE, base::Bind( |
| 169 &MessageLoop::Quit, base::Unretained(MessageLoop::current()))); |
| 149 | 170 |
| 150 // Now kick things off with the SEH block active. | 171 // Now kick things off with the SEH block active. |
| 151 MessageLoop::current()->set_exception_restoration(true); | 172 MessageLoop::current()->set_exception_restoration(true); |
| 152 MessageLoop::current()->Run(); | 173 MessageLoop::current()->Run(); |
| 153 MessageLoop::current()->set_exception_restoration(false); | 174 MessageLoop::current()->set_exception_restoration(false); |
| 154 | 175 |
| 155 EXPECT_EQ(foo->test_count(), 105); | 176 EXPECT_EQ(foo->test_count(), 105); |
| 156 EXPECT_EQ(foo->result(), "abacad"); | 177 EXPECT_EQ(foo->result(), "abacad"); |
| 157 } | 178 } |
| 158 | 179 |
| 159 // This class runs slowly to simulate a large amount of work being done. | 180 // This function runs slowly to simulate a large amount of work being done. |
| 160 class SlowTask : public Task { | 181 static void SlowFunc(int pause_ms, int* quit_counter) { |
| 161 public: | 182 PlatformThread::Sleep(pause_ms); |
| 162 SlowTask(int pause_ms, int* quit_counter) | 183 if (--(*quit_counter) == 0) |
| 163 : pause_ms_(pause_ms), quit_counter_(quit_counter) { | |
| 164 } | |
| 165 virtual void Run() { | |
| 166 PlatformThread::Sleep(pause_ms_); | |
| 167 if (--(*quit_counter_) == 0) | |
| 168 MessageLoop::current()->Quit(); | 184 MessageLoop::current()->Quit(); |
| 169 } | 185 } |
| 170 private: | |
| 171 int pause_ms_; | |
| 172 int* quit_counter_; | |
| 173 }; | |
| 174 | 186 |
| 175 // This class records the time when Run was called in a Time object, which is | 187 // This function records the time when Run was called in a Time object, which is |
| 176 // useful for building a variety of MessageLoop tests. | 188 // useful for building a variety of MessageLoop tests. |
| 177 class RecordRunTimeTask : public SlowTask { | 189 static void RecordRunTimeFunc(Time* run_time, int* quit_counter) { |
| 178 public: | 190 *run_time = Time::Now(); |
| 179 RecordRunTimeTask(Time* run_time, int* quit_counter) | 191 |
| 180 : SlowTask(10, quit_counter), run_time_(run_time) { | |
| 181 } | |
| 182 virtual void Run() { | |
| 183 *run_time_ = Time::Now(); | |
| 184 // Cause our Run function to take some time to execute. As a result we can | 192 // Cause our Run function to take some time to execute. As a result we can |
| 185 // count on subsequent RecordRunTimeTask objects running at a future time, | 193 // count on subsequent RecordRunTimeFunc()s running at a future time, |
| 186 // without worry about the resolution of our system clock being an issue. | 194 // without worry about the resolution of our system clock being an issue. |
| 187 SlowTask::Run(); | 195 SlowFunc(10, quit_counter); |
| 188 } | 196 } |
| 189 private: | |
| 190 Time* run_time_; | |
| 191 }; | |
| 192 | 197 |
| 193 void RunTest_PostDelayedTask_Basic(MessageLoop::Type message_loop_type) { | 198 void RunTest_PostDelayedClosure_Basic(MessageLoop::Type message_loop_type) { |
| 194 MessageLoop loop(message_loop_type); | 199 MessageLoop loop(message_loop_type); |
| 195 | 200 |
| 196 // Test that PostDelayedTask results in a delayed task. | 201 // Test that PostDelayedClosure results in a delayed task. |
| 197 | 202 |
| 198 const int kDelayMS = 100; | 203 const int kDelayMS = 100; |
| 199 | 204 |
| 200 int num_tasks = 1; | 205 int num_tasks = 1; |
| 201 Time run_time; | 206 Time run_time; |
| 202 | 207 |
| 203 loop.PostDelayedTask( | 208 loop.PostDelayedClosure( |
| 204 FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), kDelayMS); | 209 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time, &num_tasks), |
| 210 kDelayMS); |
| 205 | 211 |
| 206 Time time_before_run = Time::Now(); | 212 Time time_before_run = Time::Now(); |
| 207 loop.Run(); | 213 loop.Run(); |
| 208 Time time_after_run = Time::Now(); | 214 Time time_after_run = Time::Now(); |
| 209 | 215 |
| 210 EXPECT_EQ(0, num_tasks); | 216 EXPECT_EQ(0, num_tasks); |
| 211 EXPECT_LT(kDelayMS, (time_after_run - time_before_run).InMilliseconds()); | 217 EXPECT_LT(kDelayMS, (time_after_run - time_before_run).InMilliseconds()); |
| 212 } | 218 } |
| 213 | 219 |
| 214 void RunTest_PostDelayedTask_InDelayOrder(MessageLoop::Type message_loop_type) { | 220 void RunTest_PostDelayedClosure_InDelayOrder( |
| 221 MessageLoop::Type message_loop_type) { |
| 215 MessageLoop loop(message_loop_type); | 222 MessageLoop loop(message_loop_type); |
| 216 | 223 |
| 217 // Test that two tasks with different delays run in the right order. | 224 // Test that two tasks with different delays run in the right order. |
| 218 | 225 |
| 219 int num_tasks = 2; | 226 int num_tasks = 2; |
| 220 Time run_time1, run_time2; | 227 Time run_time1, run_time2; |
| 221 | 228 |
| 222 loop.PostDelayedTask( | 229 loop.PostDelayedClosure( |
| 223 FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 200); | 230 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks), 200); |
| 224 // If we get a large pause in execution (due to a context switch) here, this | 231 // If we get a large pause in execution (due to a context switch) here, this |
| 225 // test could fail. | 232 // test could fail. |
| 226 loop.PostDelayedTask( | 233 loop.PostDelayedClosure( |
| 227 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10); | 234 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), 10); |
| 228 | 235 |
| 229 loop.Run(); | 236 loop.Run(); |
| 230 EXPECT_EQ(0, num_tasks); | 237 EXPECT_EQ(0, num_tasks); |
| 231 | 238 |
| 232 EXPECT_TRUE(run_time2 < run_time1); | 239 EXPECT_TRUE(run_time2 < run_time1); |
| 233 } | 240 } |
| 234 | 241 |
| 235 void RunTest_PostDelayedTask_InPostOrder(MessageLoop::Type message_loop_type) { | 242 void RunTest_PostDelayedClosure_InPostOrder( |
| 243 MessageLoop::Type message_loop_type) { |
| 236 MessageLoop loop(message_loop_type); | 244 MessageLoop loop(message_loop_type); |
| 237 | 245 |
| 238 // Test that two tasks with the same delay run in the order in which they | 246 // Test that two tasks with the same delay run in the order in which they |
| 239 // were posted. | 247 // were posted. |
| 240 // | 248 // |
| 241 // NOTE: This is actually an approximate test since the API only takes a | 249 // NOTE: This is actually an approximate test since the API only takes a |
| 242 // "delay" parameter, so we are not exactly simulating two tasks that get | 250 // "delay" parameter, so we are not exactly simulating two tasks that get |
| 243 // posted at the exact same time. It would be nice if the API allowed us to | 251 // posted at the exact same time. It would be nice if the API allowed us to |
| 244 // specify the desired run time. | 252 // specify the desired run time. |
| 245 | 253 |
| 246 const int kDelayMS = 100; | 254 const int kDelayMS = 100; |
| 247 | 255 |
| 248 int num_tasks = 2; | 256 int num_tasks = 2; |
| 249 Time run_time1, run_time2; | 257 Time run_time1, run_time2; |
| 250 | 258 |
| 251 loop.PostDelayedTask( | 259 loop.PostDelayedClosure( |
| 252 FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), kDelayMS); | 260 FROM_HERE, |
| 253 loop.PostDelayedTask( | 261 base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks), |
| 254 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), kDelayMS); | 262 kDelayMS); |
| 263 loop.PostDelayedClosure( |
| 264 FROM_HERE, |
| 265 base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), |
| 266 kDelayMS); |
| 255 | 267 |
| 256 loop.Run(); | 268 loop.Run(); |
| 257 EXPECT_EQ(0, num_tasks); | 269 EXPECT_EQ(0, num_tasks); |
| 258 | 270 |
| 259 EXPECT_TRUE(run_time1 < run_time2); | 271 EXPECT_TRUE(run_time1 < run_time2); |
| 260 } | 272 } |
| 261 | 273 |
| 262 void RunTest_PostDelayedTask_InPostOrder_2( | 274 void RunTest_PostDelayedClosure_InPostOrder_2( |
| 263 MessageLoop::Type message_loop_type) { | 275 MessageLoop::Type message_loop_type) { |
| 264 MessageLoop loop(message_loop_type); | 276 MessageLoop loop(message_loop_type); |
| 265 | 277 |
| 266 // Test that a delayed task still runs after a normal tasks even if the | 278 // Test that a delayed task still runs after a normal tasks even if the |
| 267 // normal tasks take a long time to run. | 279 // normal tasks take a long time to run. |
| 268 | 280 |
| 269 const int kPauseMS = 50; | 281 const int kPauseMS = 50; |
| 270 | 282 |
| 271 int num_tasks = 2; | 283 int num_tasks = 2; |
| 272 Time run_time; | 284 Time run_time; |
| 273 | 285 |
| 274 loop.PostTask( | 286 loop.PostClosure( |
| 275 FROM_HERE, new SlowTask(kPauseMS, &num_tasks)); | 287 FROM_HERE, base::Bind(&SlowFunc, kPauseMS, &num_tasks)); |
| 276 loop.PostDelayedTask( | 288 loop.PostDelayedClosure( |
| 277 FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 10); | 289 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time, &num_tasks), 10); |
| 278 | 290 |
| 279 Time time_before_run = Time::Now(); | 291 Time time_before_run = Time::Now(); |
| 280 loop.Run(); | 292 loop.Run(); |
| 281 Time time_after_run = Time::Now(); | 293 Time time_after_run = Time::Now(); |
| 282 | 294 |
| 283 EXPECT_EQ(0, num_tasks); | 295 EXPECT_EQ(0, num_tasks); |
| 284 | 296 |
| 285 EXPECT_LT(kPauseMS, (time_after_run - time_before_run).InMilliseconds()); | 297 EXPECT_LT(kPauseMS, (time_after_run - time_before_run).InMilliseconds()); |
| 286 } | 298 } |
| 287 | 299 |
| 288 void RunTest_PostDelayedTask_InPostOrder_3( | 300 void RunTest_PostDelayedClosure_InPostOrder_3( |
| 289 MessageLoop::Type message_loop_type) { | 301 MessageLoop::Type message_loop_type) { |
| 290 MessageLoop loop(message_loop_type); | 302 MessageLoop loop(message_loop_type); |
| 291 | 303 |
| 292 // Test that a delayed task still runs after a pile of normal tasks. The key | 304 // Test that a delayed task still runs after a pile of normal tasks. The key |
| 293 // difference between this test and the previous one is that here we return | 305 // difference between this test and the previous one is that here we return |
| 294 // the MessageLoop a lot so we give the MessageLoop plenty of opportunities | 306 // the MessageLoop a lot so we give the MessageLoop plenty of opportunities |
| 295 // to maybe run the delayed task. It should know not to do so until the | 307 // to maybe run the delayed task. It should know not to do so until the |
| 296 // delayed task's delay has passed. | 308 // delayed task's delay has passed. |
| 297 | 309 |
| 298 int num_tasks = 11; | 310 int num_tasks = 11; |
| 299 Time run_time1, run_time2; | 311 Time run_time1, run_time2; |
| 300 | 312 |
| 301 // Clutter the ML with tasks. | 313 // Clutter the ML with tasks. |
| 302 for (int i = 1; i < num_tasks; ++i) | 314 for (int i = 1; i < num_tasks; ++i) |
| 303 loop.PostTask(FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks)); | 315 loop.PostClosure(FROM_HERE, |
| 316 base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks)); |
| 304 | 317 |
| 305 loop.PostDelayedTask( | 318 loop.PostDelayedClosure( |
| 306 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 1); | 319 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), 1); |
| 307 | 320 |
| 308 loop.Run(); | 321 loop.Run(); |
| 309 EXPECT_EQ(0, num_tasks); | 322 EXPECT_EQ(0, num_tasks); |
| 310 | 323 |
| 311 EXPECT_TRUE(run_time2 > run_time1); | 324 EXPECT_TRUE(run_time2 > run_time1); |
| 312 } | 325 } |
| 313 | 326 |
| 314 void RunTest_PostDelayedTask_SharedTimer(MessageLoop::Type message_loop_type) { | 327 void RunTest_PostDelayedClosure_SharedTimer( |
| 328 MessageLoop::Type message_loop_type) { |
| 315 MessageLoop loop(message_loop_type); | 329 MessageLoop loop(message_loop_type); |
| 316 | 330 |
| 317 // Test that the interval of the timer, used to run the next delayed task, is | 331 // Test that the interval of the timer, used to run the next delayed task, is |
| 318 // set to a value corresponding to when the next delayed task should run. | 332 // set to a value corresponding to when the next delayed task should run. |
| 319 | 333 |
| 320 // By setting num_tasks to 1, we ensure that the first task to run causes the | 334 // By setting num_tasks to 1, we ensure that the first task to run causes the |
| 321 // run loop to exit. | 335 // run loop to exit. |
| 322 int num_tasks = 1; | 336 int num_tasks = 1; |
| 323 Time run_time1, run_time2; | 337 Time run_time1, run_time2; |
| 324 | 338 |
| 325 loop.PostDelayedTask( | 339 loop.PostDelayedClosure( |
| 326 FROM_HERE, new RecordRunTimeTask(&run_time1, &num_tasks), 1000000); | 340 FROM_HERE, |
| 327 loop.PostDelayedTask( | 341 base::Bind(&RecordRunTimeFunc, &run_time1, &num_tasks), |
| 328 FROM_HERE, new RecordRunTimeTask(&run_time2, &num_tasks), 10); | 342 1000000); |
| 343 loop.PostDelayedClosure( |
| 344 FROM_HERE, base::Bind(&RecordRunTimeFunc, &run_time2, &num_tasks), 10); |
| 329 | 345 |
| 330 Time start_time = Time::Now(); | 346 Time start_time = Time::Now(); |
| 331 | 347 |
| 332 loop.Run(); | 348 loop.Run(); |
| 333 EXPECT_EQ(0, num_tasks); | 349 EXPECT_EQ(0, num_tasks); |
| 334 | 350 |
| 335 // Ensure that we ran in far less time than the slower timer. | 351 // Ensure that we ran in far less time than the slower timer. |
| 336 TimeDelta total_time = Time::Now() - start_time; | 352 TimeDelta total_time = Time::Now() - start_time; |
| 337 EXPECT_GT(5000, total_time.InMilliseconds()); | 353 EXPECT_GT(5000, total_time.InMilliseconds()); |
| 338 | 354 |
| 339 // In case both timers somehow run at nearly the same time, sleep a little | 355 // In case both timers somehow run at nearly the same time, sleep a little |
| 340 // and then run all pending to force them both to have run. This is just | 356 // and then run all pending to force them both to have run. This is just |
| 341 // encouraging flakiness if there is any. | 357 // encouraging flakiness if there is any. |
| 342 PlatformThread::Sleep(100); | 358 PlatformThread::Sleep(100); |
| 343 loop.RunAllPending(); | 359 loop.RunAllPending(); |
| 344 | 360 |
| 345 EXPECT_TRUE(run_time1.is_null()); | 361 EXPECT_TRUE(run_time1.is_null()); |
| 346 EXPECT_FALSE(run_time2.is_null()); | 362 EXPECT_FALSE(run_time2.is_null()); |
| 347 } | 363 } |
| 348 | 364 |
| 349 #if defined(OS_WIN) | 365 #if defined(OS_WIN) |
| 350 | 366 |
| 351 class SubPumpTask : public Task { | 367 void SubPumpFunc() { |
| 352 public: | 368 MessageLoop::current()->SetNestableTasksAllowed(true); |
| 353 virtual void Run() { | 369 MSG msg; |
| 354 MessageLoop::current()->SetNestableTasksAllowed(true); | 370 while (GetMessage(&msg, NULL, 0, 0)) { |
| 355 MSG msg; | 371 TranslateMessage(&msg); |
| 356 while (GetMessage(&msg, NULL, 0, 0)) { | 372 DispatchMessage(&msg); |
| 357 TranslateMessage(&msg); | |
| 358 DispatchMessage(&msg); | |
| 359 } | |
| 360 MessageLoop::current()->Quit(); | |
| 361 } | 373 } |
| 362 }; | 374 MessageLoop::current()->Quit(); |
| 375 } |
| 363 | 376 |
| 364 class SubPumpQuitTask : public Task { | 377 void RunTest_PostDelayedClosure_SharedTimer_SubPump() { |
| 365 public: | |
| 366 SubPumpQuitTask() { | |
| 367 } | |
| 368 virtual void Run() { | |
| 369 PostQuitMessage(0); | |
| 370 } | |
| 371 }; | |
| 372 | |
| 373 void RunTest_PostDelayedTask_SharedTimer_SubPump() { | |
| 374 MessageLoop loop(MessageLoop::TYPE_UI); | 378 MessageLoop loop(MessageLoop::TYPE_UI); |
| 375 | 379 |
| 376 // Test that the interval of the timer, used to run the next delayed task, is | 380 // Test that the interval of the timer, used to run the next delayed task, is |
| 377 // set to a value corresponding to when the next delayed task should run. | 381 // set to a value corresponding to when the next delayed task should run. |
| 378 | 382 |
| 379 // By setting num_tasks to 1, we ensure that the first task to run causes the | 383 // By setting num_tasks to 1, we ensure that the first task to run causes the |
| 380 // run loop to exit. | 384 // run loop to exit. |
| 381 int num_tasks = 1; | 385 int num_tasks = 1; |
| 382 Time run_time; | 386 Time run_time; |
| 383 | 387 |
| 384 loop.PostTask(FROM_HERE, new SubPumpTask()); | 388 loop.PostClosure(FROM_HERE, base::Bind(&SubPumpFunc)); |
| 385 | 389 |
| 386 // This very delayed task should never run. | 390 // This very delayed task should never run. |
| 387 loop.PostDelayedTask( | 391 loop.PostDelayedClosure( |
| 388 FROM_HERE, new RecordRunTimeTask(&run_time, &num_tasks), 1000000); | 392 FROM_HERE, |
| 393 base::Bind(&RecordRunTimeFunc, &run_time, &num_tasks), |
| 394 1000000); |
| 389 | 395 |
| 390 // This slightly delayed task should run from within SubPumpTask::Run(). | 396 // This slightly delayed task should run from within SubPumpFunc). |
| 391 loop.PostDelayedTask( | 397 loop.PostDelayedClosure(FROM_HERE, base::Bind(&PostQuitMessage, 0), 10); |
| 392 FROM_HERE, new SubPumpQuitTask(), 10); | |
| 393 | 398 |
| 394 Time start_time = Time::Now(); | 399 Time start_time = Time::Now(); |
| 395 | 400 |
| 396 loop.Run(); | 401 loop.Run(); |
| 397 EXPECT_EQ(1, num_tasks); | 402 EXPECT_EQ(1, num_tasks); |
| 398 | 403 |
| 399 // Ensure that we ran in far less time than the slower timer. | 404 // Ensure that we ran in far less time than the slower timer. |
| 400 TimeDelta total_time = Time::Now() - start_time; | 405 TimeDelta total_time = Time::Now() - start_time; |
| 401 EXPECT_GT(5000, total_time.InMilliseconds()); | 406 EXPECT_GT(5000, total_time.InMilliseconds()); |
| 402 | 407 |
| 403 // In case both timers somehow run at nearly the same time, sleep a little | 408 // In case both timers somehow run at nearly the same time, sleep a little |
| 404 // and then run all pending to force them both to have run. This is just | 409 // and then run all pending to force them both to have run. This is just |
| 405 // encouraging flakiness if there is any. | 410 // encouraging flakiness if there is any. |
| 406 PlatformThread::Sleep(100); | 411 PlatformThread::Sleep(100); |
| 407 loop.RunAllPending(); | 412 loop.RunAllPending(); |
| 408 | 413 |
| 409 EXPECT_TRUE(run_time.is_null()); | 414 EXPECT_TRUE(run_time.is_null()); |
| 410 } | 415 } |
| 411 | 416 |
| 412 #endif // defined(OS_WIN) | 417 #endif // defined(OS_WIN) |
| 413 | 418 |
| 414 class RecordDeletionTask : public Task { | 419 class RecordDeletionProbe : public base::RefCounted<RecordDeletionProbe> { |
| 415 public: | 420 public: |
| 416 RecordDeletionTask(Task* post_on_delete, bool* was_deleted) | 421 RecordDeletionProbe(RecordDeletionProbe* post_on_delete, bool* was_deleted) |
| 417 : post_on_delete_(post_on_delete), was_deleted_(was_deleted) { | 422 : post_on_delete_(post_on_delete), was_deleted_(was_deleted) { |
| 418 } | 423 } |
| 419 ~RecordDeletionTask() { | 424 ~RecordDeletionProbe() { |
| 420 *was_deleted_ = true; | 425 *was_deleted_ = true; |
| 421 if (post_on_delete_) | 426 if (post_on_delete_) |
| 422 MessageLoop::current()->PostTask(FROM_HERE, post_on_delete_); | 427 MessageLoop::current()->PostClosure( |
| 428 FROM_HERE, |
| 429 base::Bind(&RecordDeletionProbe::Run, post_on_delete_.get())); |
| 423 } | 430 } |
| 424 virtual void Run() {} | 431 virtual void Run() {} |
| 425 private: | 432 private: |
| 426 Task* post_on_delete_; | 433 scoped_refptr<RecordDeletionProbe> post_on_delete_; |
| 427 bool* was_deleted_; | 434 bool* was_deleted_; |
| 428 }; | 435 }; |
| 429 | 436 |
| 430 void RunTest_EnsureTaskDeletion(MessageLoop::Type message_loop_type) { | 437 void RunTest_EnsureDeletion(MessageLoop::Type message_loop_type) { |
| 431 bool a_was_deleted = false; | 438 bool a_was_deleted = false; |
| 432 bool b_was_deleted = false; | 439 bool b_was_deleted = false; |
| 433 { | 440 { |
| 434 MessageLoop loop(message_loop_type); | 441 MessageLoop loop(message_loop_type); |
| 435 loop.PostTask( | 442 loop.PostClosure( |
| 436 FROM_HERE, new RecordDeletionTask(NULL, &a_was_deleted)); | 443 FROM_HERE, base::Bind(&RecordDeletionProbe::Run, |
| 437 loop.PostDelayedTask( | 444 new RecordDeletionProbe(NULL, &a_was_deleted))); |
| 438 FROM_HERE, new RecordDeletionTask(NULL, &b_was_deleted), 1000); | 445 loop.PostDelayedClosure( |
| 446 FROM_HERE, base::Bind(&RecordDeletionProbe::Run, |
| 447 new RecordDeletionProbe(NULL, &b_was_deleted)), |
| 448 1000); // TODO(ajwong): Do we really need 1000ms here? |
| 439 } | 449 } |
| 440 EXPECT_TRUE(a_was_deleted); | 450 EXPECT_TRUE(a_was_deleted); |
| 441 EXPECT_TRUE(b_was_deleted); | 451 EXPECT_TRUE(b_was_deleted); |
| 442 } | 452 } |
| 443 | 453 |
| 444 void RunTest_EnsureTaskDeletion_Chain(MessageLoop::Type message_loop_type) { | 454 void RunTest_EnsureDeletion_Chain(MessageLoop::Type message_loop_type) { |
| 445 bool a_was_deleted = false; | 455 bool a_was_deleted = false; |
| 446 bool b_was_deleted = false; | 456 bool b_was_deleted = false; |
| 447 bool c_was_deleted = false; | 457 bool c_was_deleted = false; |
| 448 { | 458 { |
| 449 MessageLoop loop(message_loop_type); | 459 MessageLoop loop(message_loop_type); |
| 450 RecordDeletionTask* a = new RecordDeletionTask(NULL, &a_was_deleted); | 460 // The scoped_refptr for each of the below is held either by the chained |
| 451 RecordDeletionTask* b = new RecordDeletionTask(a, &b_was_deleted); | 461 // RecordDeletionProbe, or the bound RecordDeletionProbe::Run() callback. |
| 452 RecordDeletionTask* c = new RecordDeletionTask(b, &c_was_deleted); | 462 RecordDeletionProbe* a = new RecordDeletionProbe(NULL, &a_was_deleted); |
| 453 loop.PostTask(FROM_HERE, c); | 463 RecordDeletionProbe* b = new RecordDeletionProbe(a, &b_was_deleted); |
| 464 RecordDeletionProbe* c = new RecordDeletionProbe(b, &c_was_deleted); |
| 465 loop.PostClosure(FROM_HERE, base::Bind(&RecordDeletionProbe::Run, c)); |
| 454 } | 466 } |
| 455 EXPECT_TRUE(a_was_deleted); | 467 EXPECT_TRUE(a_was_deleted); |
| 456 EXPECT_TRUE(b_was_deleted); | 468 EXPECT_TRUE(b_was_deleted); |
| 457 EXPECT_TRUE(c_was_deleted); | 469 EXPECT_TRUE(c_was_deleted); |
| 458 } | 470 } |
| 459 | 471 |
| 460 class NestingTest : public Task { | 472 void NestingFunc(int* depth) { |
| 461 public: | 473 if (*depth > 0) { |
| 462 explicit NestingTest(int* depth) : depth_(depth) { | 474 *depth -= 1; |
| 475 MessageLoop::current()->PostClosure(FROM_HERE, |
| 476 base::Bind(&NestingFunc, depth)); |
| 477 |
| 478 MessageLoop::current()->SetNestableTasksAllowed(true); |
| 479 MessageLoop::current()->Run(); |
| 463 } | 480 } |
| 464 void Run() { | 481 MessageLoop::current()->Quit(); |
| 465 if (*depth_ > 0) { | 482 } |
| 466 *depth_ -= 1; | |
| 467 MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(depth_)); | |
| 468 | |
| 469 MessageLoop::current()->SetNestableTasksAllowed(true); | |
| 470 MessageLoop::current()->Run(); | |
| 471 } | |
| 472 MessageLoop::current()->Quit(); | |
| 473 } | |
| 474 private: | |
| 475 int* depth_; | |
| 476 }; | |
| 477 | 483 |
| 478 #if defined(OS_WIN) | 484 #if defined(OS_WIN) |
| 479 | 485 |
| 480 LONG WINAPI BadExceptionHandler(EXCEPTION_POINTERS *ex_info) { | 486 LONG WINAPI BadExceptionHandler(EXCEPTION_POINTERS *ex_info) { |
| 481 ADD_FAILURE() << "bad exception handler"; | 487 ADD_FAILURE() << "bad exception handler"; |
| 482 ::ExitProcess(ex_info->ExceptionRecord->ExceptionCode); | 488 ::ExitProcess(ex_info->ExceptionRecord->ExceptionCode); |
| 483 return EXCEPTION_EXECUTE_HANDLER; | 489 return EXCEPTION_EXECUTE_HANDLER; |
| 484 } | 490 } |
| 485 | 491 |
| 486 // This task throws an SEH exception: initially write to an invalid address. | 492 // This task throws an SEH exception: initially write to an invalid address. |
| 487 // If the right SEH filter is installed, it will fix the error. | 493 // If the right SEH filter is installed, it will fix the error. |
| 488 class CrasherTask : public Task { | 494 class Crasher : public base::RefCounted<Crasher> { |
| 489 public: | 495 public: |
| 490 // Ctor. If trash_SEH_handler is true, the task will override the unhandled | 496 // Ctor. If trash_SEH_handler is true, the task will override the unhandled |
| 491 // exception handler with one sure to crash this test. | 497 // exception handler with one sure to crash this test. |
| 492 explicit CrasherTask(bool trash_SEH_handler) | 498 explicit Crasher(bool trash_SEH_handler) |
| 493 : trash_SEH_handler_(trash_SEH_handler) { | 499 : trash_SEH_handler_(trash_SEH_handler) { |
| 494 } | 500 } |
| 501 |
| 495 void Run() { | 502 void Run() { |
| 496 PlatformThread::Sleep(1); | 503 PlatformThread::Sleep(1); |
| 497 if (trash_SEH_handler_) | 504 if (trash_SEH_handler_) |
| 498 ::SetUnhandledExceptionFilter(&BadExceptionHandler); | 505 ::SetUnhandledExceptionFilter(&BadExceptionHandler); |
| 499 // Generate a SEH fault. We do it in asm to make sure we know how to undo | 506 // Generate a SEH fault. We do it in asm to make sure we know how to undo |
| 500 // the damage. | 507 // the damage. |
| 501 | 508 |
| 502 #if defined(_M_IX86) | 509 #if defined(_M_IX86) |
| 503 | 510 |
| 504 __asm { | 511 __asm { |
| 505 mov eax, dword ptr [CrasherTask::bad_array_] | 512 mov eax, dword ptr [Crasher::bad_array_] |
| 506 mov byte ptr [eax], 66 | 513 mov byte ptr [eax], 66 |
| 507 } | 514 } |
| 508 | 515 |
| 509 #elif defined(_M_X64) | 516 #elif defined(_M_X64) |
| 510 | 517 |
| 511 bad_array_[0] = 66; | 518 bad_array_[0] = 66; |
| 512 | 519 |
| 513 #else | 520 #else |
| 514 #error "needs architecture support" | 521 #error "needs architecture support" |
| 515 #endif | 522 #endif |
| 516 | 523 |
| 517 MessageLoop::current()->Quit(); | 524 MessageLoop::current()->Quit(); |
| 518 } | 525 } |
| 519 // Points the bad array to a valid memory location. | 526 // Points the bad array to a valid memory location. |
| 520 static void FixError() { | 527 static void FixError() { |
| 521 bad_array_ = &valid_store_; | 528 bad_array_ = &valid_store_; |
| 522 } | 529 } |
| 523 | 530 |
| 524 private: | 531 private: |
| 525 bool trash_SEH_handler_; | 532 bool trash_SEH_handler_; |
| 526 static volatile char* bad_array_; | 533 static volatile char* bad_array_; |
| 527 static char valid_store_; | 534 static char valid_store_; |
| 528 }; | 535 }; |
| 529 | 536 |
| 530 volatile char* CrasherTask::bad_array_ = 0; | 537 volatile char* Crasher::bad_array_ = 0; |
| 531 char CrasherTask::valid_store_ = 0; | 538 char Crasher::valid_store_ = 0; |
| 532 | 539 |
| 533 // This SEH filter fixes the problem and retries execution. Fixing requires | 540 // This SEH filter fixes the problem and retries execution. Fixing requires |
| 534 // that the last instruction: mov eax, [CrasherTask::bad_array_] to be retried | 541 // that the last instruction: mov eax, [Crasher::bad_array_] to be retried |
| 535 // so we move the instruction pointer 5 bytes back. | 542 // so we move the instruction pointer 5 bytes back. |
| 536 LONG WINAPI HandleCrasherTaskException(EXCEPTION_POINTERS *ex_info) { | 543 LONG WINAPI HandleCrasherException(EXCEPTION_POINTERS *ex_info) { |
| 537 if (ex_info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) | 544 if (ex_info->ExceptionRecord->ExceptionCode != EXCEPTION_ACCESS_VIOLATION) |
| 538 return EXCEPTION_EXECUTE_HANDLER; | 545 return EXCEPTION_EXECUTE_HANDLER; |
| 539 | 546 |
| 540 CrasherTask::FixError(); | 547 Crasher::FixError(); |
| 541 | 548 |
| 542 #if defined(_M_IX86) | 549 #if defined(_M_IX86) |
| 543 | 550 |
| 544 ex_info->ContextRecord->Eip -= 5; | 551 ex_info->ContextRecord->Eip -= 5; |
| 545 | 552 |
| 546 #elif defined(_M_X64) | 553 #elif defined(_M_X64) |
| 547 | 554 |
| 548 ex_info->ContextRecord->Rip -= 5; | 555 ex_info->ContextRecord->Rip -= 5; |
| 549 | 556 |
| 550 #endif | 557 #endif |
| 551 | 558 |
| 552 return EXCEPTION_CONTINUE_EXECUTION; | 559 return EXCEPTION_CONTINUE_EXECUTION; |
| 553 } | 560 } |
| 554 | 561 |
| 555 void RunTest_Crasher(MessageLoop::Type message_loop_type) { | 562 void RunTest_Crasher(MessageLoop::Type message_loop_type) { |
| 556 MessageLoop loop(message_loop_type); | 563 MessageLoop loop(message_loop_type); |
| 557 | 564 |
| 558 if (::IsDebuggerPresent()) | 565 if (::IsDebuggerPresent()) |
| 559 return; | 566 return; |
| 560 | 567 |
| 561 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = | 568 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = |
| 562 ::SetUnhandledExceptionFilter(&HandleCrasherTaskException); | 569 ::SetUnhandledExceptionFilter(&HandleCrasherException); |
| 563 | 570 |
| 564 MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(false)); | 571 MessageLoop::current()->PostClosure( |
| 572 FROM_HERE, |
| 573 base::Bind(&Crasher::Run, new Crasher(false))); |
| 565 MessageLoop::current()->set_exception_restoration(true); | 574 MessageLoop::current()->set_exception_restoration(true); |
| 566 MessageLoop::current()->Run(); | 575 MessageLoop::current()->Run(); |
| 567 MessageLoop::current()->set_exception_restoration(false); | 576 MessageLoop::current()->set_exception_restoration(false); |
| 568 | 577 |
| 569 ::SetUnhandledExceptionFilter(old_SEH_filter); | 578 ::SetUnhandledExceptionFilter(old_SEH_filter); |
| 570 } | 579 } |
| 571 | 580 |
| 572 void RunTest_CrasherNasty(MessageLoop::Type message_loop_type) { | 581 void RunTest_CrasherNasty(MessageLoop::Type message_loop_type) { |
| 573 MessageLoop loop(message_loop_type); | 582 MessageLoop loop(message_loop_type); |
| 574 | 583 |
| 575 if (::IsDebuggerPresent()) | 584 if (::IsDebuggerPresent()) |
| 576 return; | 585 return; |
| 577 | 586 |
| 578 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = | 587 LPTOP_LEVEL_EXCEPTION_FILTER old_SEH_filter = |
| 579 ::SetUnhandledExceptionFilter(&HandleCrasherTaskException); | 588 ::SetUnhandledExceptionFilter(&HandleCrasherException); |
| 580 | 589 |
| 581 MessageLoop::current()->PostTask(FROM_HERE, new CrasherTask(true)); | 590 MessageLoop::current()->PostClosure( |
| 591 FROM_HERE, |
| 592 base::Bind(&Crasher::Run, new Crasher(true))); |
| 582 MessageLoop::current()->set_exception_restoration(true); | 593 MessageLoop::current()->set_exception_restoration(true); |
| 583 MessageLoop::current()->Run(); | 594 MessageLoop::current()->Run(); |
| 584 MessageLoop::current()->set_exception_restoration(false); | 595 MessageLoop::current()->set_exception_restoration(false); |
| 585 | 596 |
| 586 ::SetUnhandledExceptionFilter(old_SEH_filter); | 597 ::SetUnhandledExceptionFilter(old_SEH_filter); |
| 587 } | 598 } |
| 588 | 599 |
| 589 #endif // defined(OS_WIN) | 600 #endif // defined(OS_WIN) |
| 590 | 601 |
| 591 void RunTest_Nesting(MessageLoop::Type message_loop_type) { | 602 void RunTest_Nesting(MessageLoop::Type message_loop_type) { |
| 592 MessageLoop loop(message_loop_type); | 603 MessageLoop loop(message_loop_type); |
| 593 | 604 |
| 594 int depth = 100; | 605 int depth = 100; |
| 595 MessageLoop::current()->PostTask(FROM_HERE, new NestingTest(&depth)); | 606 MessageLoop::current()->PostClosure(FROM_HERE, |
| 607 base::Bind(&NestingFunc, &depth)); |
| 596 MessageLoop::current()->Run(); | 608 MessageLoop::current()->Run(); |
| 597 EXPECT_EQ(depth, 0); | 609 EXPECT_EQ(depth, 0); |
| 598 } | 610 } |
| 599 | 611 |
| 600 const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test"; | 612 const wchar_t* const kMessageBoxTitle = L"MessageLoop Unit Test"; |
| 601 | 613 |
| 602 enum TaskType { | 614 enum TaskType { |
| 603 MESSAGEBOX, | 615 MESSAGEBOX, |
| 604 ENDDIALOG, | 616 ENDDIALOG, |
| 605 RECURSIVE, | 617 RECURSIVE, |
| (...skipping 14 matching lines...) Expand all Loading... |
| 620 | 632 |
| 621 TaskType type; | 633 TaskType type; |
| 622 int cookie; | 634 int cookie; |
| 623 bool start; | 635 bool start; |
| 624 | 636 |
| 625 bool operator == (const TaskItem& other) const { | 637 bool operator == (const TaskItem& other) const { |
| 626 return type == other.type && cookie == other.cookie && start == other.start; | 638 return type == other.type && cookie == other.cookie && start == other.start; |
| 627 } | 639 } |
| 628 }; | 640 }; |
| 629 | 641 |
| 630 typedef std::vector<TaskItem> TaskList; | |
| 631 | |
| 632 std::ostream& operator <<(std::ostream& os, TaskType type) { | 642 std::ostream& operator <<(std::ostream& os, TaskType type) { |
| 633 switch (type) { | 643 switch (type) { |
| 634 case MESSAGEBOX: os << "MESSAGEBOX"; break; | 644 case MESSAGEBOX: os << "MESSAGEBOX"; break; |
| 635 case ENDDIALOG: os << "ENDDIALOG"; break; | 645 case ENDDIALOG: os << "ENDDIALOG"; break; |
| 636 case RECURSIVE: os << "RECURSIVE"; break; | 646 case RECURSIVE: os << "RECURSIVE"; break; |
| 637 case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break; | 647 case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break; |
| 638 case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break; | 648 case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break; |
| 639 case ORDERERD: os << "ORDERERD"; break; | 649 case ORDERERD: os << "ORDERERD"; break; |
| 640 case PUMPS: os << "PUMPS"; break; | 650 case PUMPS: os << "PUMPS"; break; |
| 641 case SLEEP: os << "SLEEP"; break; | 651 case SLEEP: os << "SLEEP"; break; |
| 642 default: | 652 default: |
| 643 NOTREACHED(); | 653 NOTREACHED(); |
| 644 os << "Unknown TaskType"; | 654 os << "Unknown TaskType"; |
| 645 break; | 655 break; |
| 646 } | 656 } |
| 647 return os; | 657 return os; |
| 648 } | 658 } |
| 649 | 659 |
| 650 std::ostream& operator <<(std::ostream& os, const TaskItem& item) { | 660 std::ostream& operator <<(std::ostream& os, const TaskItem& item) { |
| 651 if (item.start) | 661 if (item.start) |
| 652 return os << item.type << " " << item.cookie << " starts"; | 662 return os << item.type << " " << item.cookie << " starts"; |
| 653 else | 663 else |
| 654 return os << item.type << " " << item.cookie << " ends"; | 664 return os << item.type << " " << item.cookie << " ends"; |
| 655 } | 665 } |
| 656 | 666 |
| 657 // Saves the order the tasks ran. | 667 class TaskList { |
| 658 class OrderedTasks : public Task { | |
| 659 public: | 668 public: |
| 660 OrderedTasks(TaskList* order, int cookie) | 669 void RecordStart(TaskType type, int cookie) { |
| 661 : order_(order), | 670 TaskItem item(type, cookie, true); |
| 662 type_(ORDERERD), | 671 DVLOG(1) << item; |
| 663 cookie_(cookie) { | 672 task_list_.push_back(item); |
| 664 } | |
| 665 OrderedTasks(TaskList* order, TaskType type, int cookie) | |
| 666 : order_(order), | |
| 667 type_(type), | |
| 668 cookie_(cookie) { | |
| 669 } | 673 } |
| 670 | 674 |
| 671 void RunStart() { | 675 void RecordEnd(TaskType type, int cookie) { |
| 672 TaskItem item(type_, cookie_, true); | 676 TaskItem item(type, cookie, false); |
| 673 DVLOG(1) << item; | 677 DVLOG(1) << item; |
| 674 order_->push_back(item); | 678 task_list_.push_back(item); |
| 675 } | |
| 676 void RunEnd() { | |
| 677 TaskItem item(type_, cookie_, false); | |
| 678 DVLOG(1) << item; | |
| 679 order_->push_back(item); | |
| 680 } | 679 } |
| 681 | 680 |
| 682 virtual void Run() { | 681 size_t Size() { |
| 683 RunStart(); | 682 return task_list_.size(); |
| 684 RunEnd(); | |
| 685 } | 683 } |
| 686 | 684 |
| 687 protected: | 685 TaskItem Get(int n) { |
| 688 TaskList* order() const { | 686 return task_list_[n]; |
| 689 return order_; | |
| 690 } | |
| 691 | |
| 692 int cookie() const { | |
| 693 return cookie_; | |
| 694 } | 687 } |
| 695 | 688 |
| 696 private: | 689 private: |
| 697 TaskList* order_; | 690 std::vector<TaskItem> task_list_; |
| 698 TaskType type_; | |
| 699 int cookie_; | |
| 700 }; | 691 }; |
| 701 | 692 |
| 693 // Saves the order the tasks ran. |
| 694 void OrderedFunc(TaskList* order, int cookie) { |
| 695 order->RecordStart(ORDERERD, cookie); |
| 696 order->RecordEnd(ORDERERD, cookie); |
| 697 } |
| 698 |
| 702 #if defined(OS_WIN) | 699 #if defined(OS_WIN) |
| 703 | 700 |
| 704 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes, | 701 // MessageLoop implicitly start a "modal message loop". Modal dialog boxes, |
| 705 // common controls (like OpenFile) and StartDoc printing function can cause | 702 // common controls (like OpenFile) and StartDoc printing function can cause |
| 706 // implicit message loops. | 703 // implicit message loops. |
| 707 class MessageBoxTask : public OrderedTasks { | 704 void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) { |
| 708 public: | 705 order->RecordStart(MESSAGEBOX, cookie); |
| 709 MessageBoxTask(TaskList* order, int cookie, bool is_reentrant) | 706 if (is_reentrant) |
| 710 : OrderedTasks(order, MESSAGEBOX, cookie), | 707 MessageLoop::current()->SetNestableTasksAllowed(true); |
| 711 is_reentrant_(is_reentrant) { | 708 MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK); |
| 712 } | 709 order->RecordEnd(MESSAGEBOX, cookie); |
| 713 | 710 } |
| 714 virtual void Run() { | |
| 715 RunStart(); | |
| 716 if (is_reentrant_) | |
| 717 MessageLoop::current()->SetNestableTasksAllowed(true); | |
| 718 MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK); | |
| 719 RunEnd(); | |
| 720 } | |
| 721 | |
| 722 private: | |
| 723 bool is_reentrant_; | |
| 724 }; | |
| 725 | 711 |
| 726 // Will end the MessageBox. | 712 // Will end the MessageBox. |
| 727 class EndDialogTask : public OrderedTasks { | 713 void EndDialogFunc(TaskList* order, int cookie) { |
| 728 public: | 714 order->RecordStart(ENDDIALOG, cookie); |
| 729 EndDialogTask(TaskList* order, int cookie) | 715 HWND window = GetActiveWindow(); |
| 730 : OrderedTasks(order, ENDDIALOG, cookie) { | 716 if (window != NULL) { |
| 717 EXPECT_NE(EndDialog(window, IDCONTINUE), 0); |
| 718 // Cheap way to signal that the window wasn't found if RunEnd() isn't |
| 719 // called. |
| 720 order->RecordEnd(ENDDIALOG, cookie); |
| 731 } | 721 } |
| 732 | 722 } |
| 733 virtual void Run() { | |
| 734 RunStart(); | |
| 735 HWND window = GetActiveWindow(); | |
| 736 if (window != NULL) { | |
| 737 EXPECT_NE(EndDialog(window, IDCONTINUE), 0); | |
| 738 // Cheap way to signal that the window wasn't found if RunEnd() isn't | |
| 739 // called. | |
| 740 RunEnd(); | |
| 741 } | |
| 742 } | |
| 743 }; | |
| 744 | 723 |
| 745 #endif // defined(OS_WIN) | 724 #endif // defined(OS_WIN) |
| 746 | 725 |
| 747 class RecursiveTask : public OrderedTasks { | 726 void RecursiveFunc(TaskList* order, int cookie, int depth, |
| 748 public: | 727 bool is_reentrant) { |
| 749 RecursiveTask(int depth, TaskList* order, int cookie, bool is_reentrant) | 728 order->RecordStart(RECURSIVE, cookie); |
| 750 : OrderedTasks(order, RECURSIVE, cookie), | 729 if (depth > 0) { |
| 751 depth_(depth), | 730 if (is_reentrant) |
| 752 is_reentrant_(is_reentrant) { | 731 MessageLoop::current()->SetNestableTasksAllowed(true); |
| 732 MessageLoop::current()->PostClosure( |
| 733 FROM_HERE, |
| 734 base::Bind(&RecursiveFunc, order, cookie, depth - 1, is_reentrant)); |
| 753 } | 735 } |
| 736 order->RecordEnd(RECURSIVE, cookie); |
| 737 } |
| 754 | 738 |
| 755 virtual void Run() { | 739 void RecursiveSlowFunc(TaskList* order, int cookie, int depth, |
| 756 RunStart(); | 740 bool is_reentrant) { |
| 757 if (depth_ > 0) { | 741 RecursiveFunc(order, cookie, depth, is_reentrant); |
| 758 if (is_reentrant_) | 742 PlatformThread::Sleep(10); // milliseconds |
| 759 MessageLoop::current()->SetNestableTasksAllowed(true); | 743 } |
| 760 MessageLoop::current()->PostTask(FROM_HERE, | |
| 761 new RecursiveTask(depth_ - 1, order(), cookie(), is_reentrant_)); | |
| 762 } | |
| 763 RunEnd(); | |
| 764 } | |
| 765 | 744 |
| 766 private: | 745 void QuitFunc(TaskList* order, int cookie) { |
| 767 int depth_; | 746 order->RecordStart(QUITMESSAGELOOP, cookie); |
| 768 bool is_reentrant_; | 747 MessageLoop::current()->Quit(); |
| 769 }; | 748 order->RecordEnd(QUITMESSAGELOOP, cookie); |
| 749 } |
| 770 | 750 |
| 771 class RecursiveSlowTask : public RecursiveTask { | 751 void SleepFunc(TaskList* order, int cookie, int ms) { |
| 772 public: | 752 order->RecordStart(SLEEP, cookie); |
| 773 RecursiveSlowTask(int depth, TaskList* order, int cookie, bool is_reentrant) | 753 PlatformThread::Sleep(ms); |
| 774 : RecursiveTask(depth, order, cookie, is_reentrant) { | 754 order->RecordEnd(SLEEP, cookie); |
| 775 } | 755 } |
| 776 | |
| 777 virtual void Run() { | |
| 778 RecursiveTask::Run(); | |
| 779 PlatformThread::Sleep(10); // milliseconds | |
| 780 } | |
| 781 }; | |
| 782 | |
| 783 class QuitTask : public OrderedTasks { | |
| 784 public: | |
| 785 QuitTask(TaskList* order, int cookie) | |
| 786 : OrderedTasks(order, QUITMESSAGELOOP, cookie) { | |
| 787 } | |
| 788 | |
| 789 virtual void Run() { | |
| 790 RunStart(); | |
| 791 MessageLoop::current()->Quit(); | |
| 792 RunEnd(); | |
| 793 } | |
| 794 }; | |
| 795 | |
| 796 class SleepTask : public OrderedTasks { | |
| 797 public: | |
| 798 SleepTask(TaskList* order, int cookie, int ms) | |
| 799 : OrderedTasks(order, SLEEP, cookie), ms_(ms) { | |
| 800 } | |
| 801 | |
| 802 virtual void Run() { | |
| 803 RunStart(); | |
| 804 PlatformThread::Sleep(ms_); | |
| 805 RunEnd(); | |
| 806 } | |
| 807 | |
| 808 private: | |
| 809 int ms_; | |
| 810 }; | |
| 811 | 756 |
| 812 #if defined(OS_WIN) | 757 #if defined(OS_WIN) |
| 758 void RecursiveFuncWin(MessageLoop* target, |
| 759 HANDLE event, |
| 760 bool expect_window, |
| 761 TaskList* order, |
| 762 bool is_reentrant) { |
| 763 target->PostClosure(FROM_HERE, |
| 764 base::Bind(&RecursiveFunc, order, 1, 2, is_reentrant)); |
| 765 target->PostClosure(FROM_HERE, |
| 766 base::Bind(&MessageBoxFunc, order, 2, is_reentrant)); |
| 767 target->PostClosure(FROM_HERE, |
| 768 base::Bind(&RecursiveFunc, order, 3, 2, is_reentrant)); |
| 769 // The trick here is that for recursive task processing, this task will be |
| 770 // ran _inside_ the MessageBox message loop, dismissing the MessageBox |
| 771 // without a chance. |
| 772 // For non-recursive task processing, this will be executed _after_ the |
| 773 // MessageBox will have been dismissed by the code below, where |
| 774 // expect_window_ is true. |
| 775 target->PostClosure(FROM_HERE, |
| 776 base::Bind(&EndDialogFunc, order, 4)); |
| 777 target->PostClosure(FROM_HERE, |
| 778 base::Bind(&QuitFunc, order, 5)); |
| 813 | 779 |
| 814 class Recursive2Tasks : public Task { | 780 // Enforce that every tasks are sent before starting to run the main thread |
| 815 public: | 781 // message loop. |
| 816 Recursive2Tasks(MessageLoop* target, | 782 ASSERT_TRUE(SetEvent(event)); |
| 817 HANDLE event, | |
| 818 bool expect_window, | |
| 819 TaskList* order, | |
| 820 bool is_reentrant) | |
| 821 : target_(target), | |
| 822 event_(event), | |
| 823 expect_window_(expect_window), | |
| 824 order_(order), | |
| 825 is_reentrant_(is_reentrant) { | |
| 826 } | |
| 827 | 783 |
| 828 virtual void Run() { | 784 // Poll for the MessageBox. Don't do this at home! At the speed we do it, |
| 829 target_->PostTask(FROM_HERE, | 785 // you will never realize one MessageBox was shown. |
| 830 new RecursiveTask(2, order_, 1, is_reentrant_)); | 786 for (; expect_window;) { |
| 831 target_->PostTask(FROM_HERE, | 787 HWND window = FindWindow(L"#32770", kMessageBoxTitle); |
| 832 new MessageBoxTask(order_, 2, is_reentrant_)); | 788 if (window) { |
| 833 target_->PostTask(FROM_HERE, | 789 // Dismiss it. |
| 834 new RecursiveTask(2, order_, 3, is_reentrant_)); | 790 for (;;) { |
| 835 // The trick here is that for recursive task processing, this task will be | 791 HWND button = FindWindowEx(window, NULL, L"Button", NULL); |
| 836 // ran _inside_ the MessageBox message loop, dismissing the MessageBox | 792 if (button != NULL) { |
| 837 // without a chance. | 793 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0)); |
| 838 // For non-recursive task processing, this will be executed _after_ the | 794 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0)); |
| 839 // MessageBox will have been dismissed by the code below, where | 795 break; |
| 840 // expect_window_ is true. | |
| 841 target_->PostTask(FROM_HERE, new EndDialogTask(order_, 4)); | |
| 842 target_->PostTask(FROM_HERE, new QuitTask(order_, 5)); | |
| 843 | |
| 844 // Enforce that every tasks are sent before starting to run the main thread | |
| 845 // message loop. | |
| 846 ASSERT_TRUE(SetEvent(event_)); | |
| 847 | |
| 848 // Poll for the MessageBox. Don't do this at home! At the speed we do it, | |
| 849 // you will never realize one MessageBox was shown. | |
| 850 for (; expect_window_;) { | |
| 851 HWND window = FindWindow(L"#32770", kMessageBoxTitle); | |
| 852 if (window) { | |
| 853 // Dismiss it. | |
| 854 for (;;) { | |
| 855 HWND button = FindWindowEx(window, NULL, L"Button", NULL); | |
| 856 if (button != NULL) { | |
| 857 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0)); | |
| 858 EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0)); | |
| 859 break; | |
| 860 } | |
| 861 } | 796 } |
| 862 break; | |
| 863 } | 797 } |
| 798 break; |
| 864 } | 799 } |
| 865 } | 800 } |
| 866 | 801 } |
| 867 private: | |
| 868 MessageLoop* target_; | |
| 869 HANDLE event_; | |
| 870 TaskList* order_; | |
| 871 bool expect_window_; | |
| 872 bool is_reentrant_; | |
| 873 }; | |
| 874 | 802 |
| 875 #endif // defined(OS_WIN) | 803 #endif // defined(OS_WIN) |
| 876 | 804 |
| 877 void RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type) { | 805 void RunTest_RecursiveDenial1(MessageLoop::Type message_loop_type) { |
| 878 MessageLoop loop(message_loop_type); | 806 MessageLoop loop(message_loop_type); |
| 879 | 807 |
| 880 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed()); | 808 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed()); |
| 881 TaskList order; | 809 TaskList order; |
| 882 MessageLoop::current()->PostTask(FROM_HERE, | 810 MessageLoop::current()->PostClosure( |
| 883 new RecursiveTask(2, &order, 1, false)); | 811 FROM_HERE, |
| 884 MessageLoop::current()->PostTask(FROM_HERE, | 812 base::Bind(&RecursiveFunc, &order, 1, 2, false)); |
| 885 new RecursiveTask(2, &order, 2, false)); | 813 MessageLoop::current()->PostClosure( |
| 886 MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3)); | 814 FROM_HERE, |
| 815 base::Bind(&RecursiveFunc, &order, 2, 2, false)); |
| 816 MessageLoop::current()->PostClosure( |
| 817 FROM_HERE, |
| 818 base::Bind(&QuitFunc, &order, 3)); |
| 887 | 819 |
| 888 MessageLoop::current()->Run(); | 820 MessageLoop::current()->Run(); |
| 889 | 821 |
| 890 // FIFO order. | 822 // FIFO order. |
| 891 ASSERT_EQ(14U, order.size()); | 823 ASSERT_EQ(14U, order.Size()); |
| 892 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); | 824 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); |
| 893 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); | 825 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); |
| 894 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); | 826 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true)); |
| 895 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); | 827 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false)); |
| 896 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); | 828 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true)); |
| 897 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); | 829 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false)); |
| 898 EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true)); | 830 EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true)); |
| 899 EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false)); | 831 EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false)); |
| 900 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); | 832 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true)); |
| 901 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); | 833 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false)); |
| 902 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); | 834 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true)); |
| 903 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); | 835 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false)); |
| 904 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true)); | 836 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true)); |
| 905 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false)); | 837 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false)); |
| 906 } | 838 } |
| 907 | 839 |
| 908 void RunTest_RecursiveDenial3(MessageLoop::Type message_loop_type) { | 840 void RunTest_RecursiveDenial3(MessageLoop::Type message_loop_type) { |
| 909 MessageLoop loop(message_loop_type); | 841 MessageLoop loop(message_loop_type); |
| 910 | 842 |
| 911 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed()); | 843 EXPECT_TRUE(MessageLoop::current()->NestableTasksAllowed()); |
| 912 TaskList order; | 844 TaskList order; |
| 913 MessageLoop::current()->PostTask(FROM_HERE, | 845 MessageLoop::current()->PostClosure( |
| 914 new RecursiveSlowTask(2, &order, 1, false)); | 846 FROM_HERE, base::Bind(&RecursiveSlowFunc, &order, 1, 2, false)); |
| 915 MessageLoop::current()->PostTask(FROM_HERE, | 847 MessageLoop::current()->PostClosure( |
| 916 new RecursiveSlowTask(2, &order, 2, false)); | 848 FROM_HERE, base::Bind(&RecursiveSlowFunc, &order, 2, 2, false)); |
| 917 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 849 MessageLoop::current()->PostDelayedClosure( |
| 918 new OrderedTasks(&order, 3), 5); | 850 FROM_HERE, base::Bind(&OrderedFunc, &order, 3), 5); |
| 919 MessageLoop::current()->PostDelayedTask(FROM_HERE, | 851 MessageLoop::current()->PostDelayedClosure( |
| 920 new QuitTask(&order, 4), 5); | 852 FROM_HERE, base::Bind(&QuitFunc, &order, 4), 5); |
| 921 | 853 |
| 922 MessageLoop::current()->Run(); | 854 MessageLoop::current()->Run(); |
| 923 | 855 |
| 924 // FIFO order. | 856 // FIFO order. |
| 925 ASSERT_EQ(16U, order.size()); | 857 ASSERT_EQ(16U, order.Size()); |
| 926 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); | 858 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); |
| 927 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); | 859 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); |
| 928 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); | 860 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true)); |
| 929 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); | 861 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false)); |
| 930 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 1, true)); | 862 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 1, true)); |
| 931 EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 1, false)); | 863 EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 1, false)); |
| 932 EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 3, true)); | 864 EXPECT_EQ(order.Get(6), TaskItem(ORDERERD, 3, true)); |
| 933 EXPECT_EQ(order[ 7], TaskItem(ORDERERD, 3, false)); | 865 EXPECT_EQ(order.Get(7), TaskItem(ORDERERD, 3, false)); |
| 934 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); | 866 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true)); |
| 935 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); | 867 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false)); |
| 936 EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 4, true)); | 868 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 4, true)); |
| 937 EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 4, false)); | 869 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 4, false)); |
| 938 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 1, true)); | 870 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 1, true)); |
| 939 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, false)); | 871 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, false)); |
| 940 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 2, true)); | 872 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 2, true)); |
| 941 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 2, false)); | 873 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 2, false)); |
| 942 } | 874 } |
| 943 | 875 |
| 944 void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type) { | 876 void RunTest_RecursiveSupport1(MessageLoop::Type message_loop_type) { |
| 945 MessageLoop loop(message_loop_type); | 877 MessageLoop loop(message_loop_type); |
| 946 | 878 |
| 947 TaskList order; | 879 TaskList order; |
| 948 MessageLoop::current()->PostTask(FROM_HERE, | 880 MessageLoop::current()->PostClosure( |
| 949 new RecursiveTask(2, &order, 1, true)); | 881 FROM_HERE, |
| 950 MessageLoop::current()->PostTask(FROM_HERE, | 882 base::Bind(&RecursiveFunc, &order, 1, 2, true)); |
| 951 new RecursiveTask(2, &order, 2, true)); | 883 MessageLoop::current()->PostClosure( |
| 952 MessageLoop::current()->PostTask(FROM_HERE, | 884 FROM_HERE, |
| 953 new QuitTask(&order, 3)); | 885 base::Bind(&RecursiveFunc, &order, 2, 2, true)); |
| 886 MessageLoop::current()->PostClosure( |
| 887 FROM_HERE, |
| 888 base::Bind(&QuitFunc, &order, 3)); |
| 954 | 889 |
| 955 MessageLoop::current()->Run(); | 890 MessageLoop::current()->Run(); |
| 956 | 891 |
| 957 // FIFO order. | 892 // FIFO order. |
| 958 ASSERT_EQ(14U, order.size()); | 893 ASSERT_EQ(14U, order.Size()); |
| 959 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); | 894 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); |
| 960 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); | 895 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); |
| 961 EXPECT_EQ(order[ 2], TaskItem(RECURSIVE, 2, true)); | 896 EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true)); |
| 962 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 2, false)); | 897 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false)); |
| 963 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); | 898 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true)); |
| 964 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); | 899 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false)); |
| 965 EXPECT_EQ(order[ 6], TaskItem(RECURSIVE, 1, true)); | 900 EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true)); |
| 966 EXPECT_EQ(order[ 7], TaskItem(RECURSIVE, 1, false)); | 901 EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false)); |
| 967 EXPECT_EQ(order[ 8], TaskItem(RECURSIVE, 2, true)); | 902 EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true)); |
| 968 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 2, false)); | 903 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false)); |
| 969 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); | 904 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true)); |
| 970 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); | 905 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false)); |
| 971 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 2, true)); | 906 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true)); |
| 972 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 2, false)); | 907 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false)); |
| 973 } | 908 } |
| 974 | 909 |
| 975 #if defined(OS_WIN) | 910 #if defined(OS_WIN) |
| 976 // TODO(darin): These tests need to be ported since they test critical | 911 // TODO(darin): These tests need to be ported since they test critical |
| 977 // message loop functionality. | 912 // message loop functionality. |
| 978 | 913 |
| 979 // A side effect of this test is the generation a beep. Sorry. | 914 // A side effect of this test is the generation a beep. Sorry. |
| 980 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) { | 915 void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) { |
| 981 MessageLoop loop(message_loop_type); | 916 MessageLoop loop(message_loop_type); |
| 982 | 917 |
| 983 Thread worker("RecursiveDenial2_worker"); | 918 Thread worker("RecursiveDenial2_worker"); |
| 984 Thread::Options options; | 919 Thread::Options options; |
| 985 options.message_loop_type = message_loop_type; | 920 options.message_loop_type = message_loop_type; |
| 986 ASSERT_EQ(true, worker.StartWithOptions(options)); | 921 ASSERT_EQ(true, worker.StartWithOptions(options)); |
| 987 TaskList order; | 922 TaskList order; |
| 988 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); | 923 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); |
| 989 worker.message_loop()->PostTask(FROM_HERE, | 924 worker.message_loop()->PostClosure(FROM_HERE, |
| 990 new Recursive2Tasks(MessageLoop::current(), | 925 base::Bind(&RecursiveFuncWin, |
| 991 event, | 926 MessageLoop::current(), |
| 992 true, | 927 event.Get(), |
| 993 &order, | 928 true, |
| 994 false)); | 929 &order, |
| 930 false)); |
| 995 // Let the other thread execute. | 931 // Let the other thread execute. |
| 996 WaitForSingleObject(event, INFINITE); | 932 WaitForSingleObject(event, INFINITE); |
| 997 MessageLoop::current()->Run(); | 933 MessageLoop::current()->Run(); |
| 998 | 934 |
| 999 ASSERT_EQ(order.size(), 17); | 935 ASSERT_EQ(order.Size(), 17); |
| 1000 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); | 936 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); |
| 1001 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); | 937 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); |
| 1002 EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true)); | 938 EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true)); |
| 1003 EXPECT_EQ(order[ 3], TaskItem(MESSAGEBOX, 2, false)); | 939 EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false)); |
| 1004 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, true)); | 940 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true)); |
| 1005 EXPECT_EQ(order[ 5], TaskItem(RECURSIVE, 3, false)); | 941 EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false)); |
| 1006 // When EndDialogTask is processed, the window is already dismissed, hence no | 942 // When EndDialogFunc is processed, the window is already dismissed, hence no |
| 1007 // "end" entry. | 943 // "end" entry. |
| 1008 EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, true)); | 944 EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true)); |
| 1009 EXPECT_EQ(order[ 7], TaskItem(QUITMESSAGELOOP, 5, true)); | 945 EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true)); |
| 1010 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, false)); | 946 EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false)); |
| 1011 EXPECT_EQ(order[ 9], TaskItem(RECURSIVE, 1, true)); | 947 EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true)); |
| 1012 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, false)); | 948 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false)); |
| 1013 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 3, true)); | 949 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true)); |
| 1014 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, false)); | 950 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false)); |
| 1015 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 1, true)); | 951 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true)); |
| 1016 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, false)); | 952 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false)); |
| 1017 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 3, true)); | 953 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true)); |
| 1018 EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, false)); | 954 EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false)); |
| 1019 } | 955 } |
| 1020 | 956 |
| 1021 // A side effect of this test is the generation a beep. Sorry. This test also | 957 // A side effect of this test is the generation a beep. Sorry. This test also |
| 1022 // needs to process windows messages on the current thread. | 958 // needs to process windows messages on the current thread. |
| 1023 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) { | 959 void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) { |
| 1024 MessageLoop loop(message_loop_type); | 960 MessageLoop loop(message_loop_type); |
| 1025 | 961 |
| 1026 Thread worker("RecursiveSupport2_worker"); | 962 Thread worker("RecursiveSupport2_worker"); |
| 1027 Thread::Options options; | 963 Thread::Options options; |
| 1028 options.message_loop_type = message_loop_type; | 964 options.message_loop_type = message_loop_type; |
| 1029 ASSERT_EQ(true, worker.StartWithOptions(options)); | 965 ASSERT_EQ(true, worker.StartWithOptions(options)); |
| 1030 TaskList order; | 966 TaskList order; |
| 1031 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); | 967 base::win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL)); |
| 1032 worker.message_loop()->PostTask(FROM_HERE, | 968 worker.message_loop()->PostClosure(FROM_HERE, |
| 1033 new Recursive2Tasks(MessageLoop::current(), | 969 base::Bind(&RecursiveFuncWin, |
| 1034 event, | 970 MessageLoop::current(), |
| 1035 false, | 971 event.Get(), |
| 1036 &order, | 972 false, |
| 1037 true)); | 973 &order, |
| 974 true)); |
| 1038 // Let the other thread execute. | 975 // Let the other thread execute. |
| 1039 WaitForSingleObject(event, INFINITE); | 976 WaitForSingleObject(event, INFINITE); |
| 1040 MessageLoop::current()->Run(); | 977 MessageLoop::current()->Run(); |
| 1041 | 978 |
| 1042 ASSERT_EQ(order.size(), 18); | 979 ASSERT_EQ(order.Size(), 18); |
| 1043 EXPECT_EQ(order[ 0], TaskItem(RECURSIVE, 1, true)); | 980 EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true)); |
| 1044 EXPECT_EQ(order[ 1], TaskItem(RECURSIVE, 1, false)); | 981 EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false)); |
| 1045 EXPECT_EQ(order[ 2], TaskItem(MESSAGEBOX, 2, true)); | 982 EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true)); |
| 1046 // Note that this executes in the MessageBox modal loop. | 983 // Note that this executes in the MessageBox modal loop. |
| 1047 EXPECT_EQ(order[ 3], TaskItem(RECURSIVE, 3, true)); | 984 EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true)); |
| 1048 EXPECT_EQ(order[ 4], TaskItem(RECURSIVE, 3, false)); | 985 EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false)); |
| 1049 EXPECT_EQ(order[ 5], TaskItem(ENDDIALOG, 4, true)); | 986 EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true)); |
| 1050 EXPECT_EQ(order[ 6], TaskItem(ENDDIALOG, 4, false)); | 987 EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false)); |
| 1051 EXPECT_EQ(order[ 7], TaskItem(MESSAGEBOX, 2, false)); | 988 EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false)); |
| 1052 /* The order can subtly change here. The reason is that when RecursiveTask(1) | 989 /* The order can subtly change here. The reason is that when RecursiveFunc(1) |
| 1053 is called in the main thread, if it is faster than getting to the | 990 is called in the main thread, if it is faster than getting to the |
| 1054 PostTask(FROM_HERE, QuitTask) execution, the order of task execution can | 991 PostClosure(FROM_HERE, base::Bind(&QuitFunc) execution, the order of task |
| 1055 change. We don't care anyway that the order isn't correct. | 992 execution can change. We don't care anyway that the order isn't correct. |
| 1056 EXPECT_EQ(order[ 8], TaskItem(QUITMESSAGELOOP, 5, true)); | 993 EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true)); |
| 1057 EXPECT_EQ(order[ 9], TaskItem(QUITMESSAGELOOP, 5, false)); | 994 EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false)); |
| 1058 EXPECT_EQ(order[10], TaskItem(RECURSIVE, 1, true)); | 995 EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true)); |
| 1059 EXPECT_EQ(order[11], TaskItem(RECURSIVE, 1, false)); | 996 EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false)); |
| 1060 */ | 997 */ |
| 1061 EXPECT_EQ(order[12], TaskItem(RECURSIVE, 3, true)); | 998 EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true)); |
| 1062 EXPECT_EQ(order[13], TaskItem(RECURSIVE, 3, false)); | 999 EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false)); |
| 1063 EXPECT_EQ(order[14], TaskItem(RECURSIVE, 1, true)); | 1000 EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true)); |
| 1064 EXPECT_EQ(order[15], TaskItem(RECURSIVE, 1, false)); | 1001 EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false)); |
| 1065 EXPECT_EQ(order[16], TaskItem(RECURSIVE, 3, true)); | 1002 EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true)); |
| 1066 EXPECT_EQ(order[17], TaskItem(RECURSIVE, 3, false)); | 1003 EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false)); |
| 1067 } | 1004 } |
| 1068 | 1005 |
| 1069 #endif // defined(OS_WIN) | 1006 #endif // defined(OS_WIN) |
| 1070 | 1007 |
| 1071 class TaskThatPumps : public OrderedTasks { | 1008 void FuncThatPumps(TaskList* order, int cookie) { |
| 1072 public: | 1009 order->RecordStart(PUMPS, cookie); |
| 1073 TaskThatPumps(TaskList* order, int cookie) | 1010 bool old_state = MessageLoop::current()->NestableTasksAllowed(); |
| 1074 : OrderedTasks(order, PUMPS, cookie) { | 1011 MessageLoop::current()->SetNestableTasksAllowed(true); |
| 1075 } | 1012 MessageLoop::current()->RunAllPending(); |
| 1076 | 1013 MessageLoop::current()->SetNestableTasksAllowed(old_state); |
| 1077 virtual void Run() { | 1014 order->RecordEnd(PUMPS, cookie); |
| 1078 RunStart(); | 1015 } |
| 1079 bool old_state = MessageLoop::current()->NestableTasksAllowed(); | |
| 1080 MessageLoop::current()->SetNestableTasksAllowed(true); | |
| 1081 MessageLoop::current()->RunAllPending(); | |
| 1082 MessageLoop::current()->SetNestableTasksAllowed(old_state); | |
| 1083 RunEnd(); | |
| 1084 } | |
| 1085 }; | |
| 1086 | 1016 |
| 1087 // Tests that non nestable tasks run in FIFO if there are no nested loops. | 1017 // Tests that non nestable tasks run in FIFO if there are no nested loops. |
| 1088 void RunTest_NonNestableWithNoNesting(MessageLoop::Type message_loop_type) { | 1018 void RunTest_NonNestableWithNoNesting( |
| 1019 MessageLoop::Type message_loop_type) { |
| 1089 MessageLoop loop(message_loop_type); | 1020 MessageLoop loop(message_loop_type); |
| 1090 | 1021 |
| 1091 TaskList order; | 1022 TaskList order; |
| 1092 | 1023 |
| 1093 Task* task = new OrderedTasks(&order, 1); | 1024 MessageLoop::current()->PostNonNestableClosure( |
| 1094 MessageLoop::current()->PostNonNestableTask(FROM_HERE, task); | 1025 FROM_HERE, |
| 1095 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 2)); | 1026 base::Bind(&OrderedFunc, &order, 1)); |
| 1096 MessageLoop::current()->PostTask(FROM_HERE, new QuitTask(&order, 3)); | 1027 MessageLoop::current()->PostClosure(FROM_HERE, |
| 1028 base::Bind(&OrderedFunc, &order, 2)); |
| 1029 MessageLoop::current()->PostClosure(FROM_HERE, |
| 1030 base::Bind(&QuitFunc, &order, 3)); |
| 1097 MessageLoop::current()->Run(); | 1031 MessageLoop::current()->Run(); |
| 1098 | 1032 |
| 1099 // FIFO order. | 1033 // FIFO order. |
| 1100 ASSERT_EQ(6U, order.size()); | 1034 ASSERT_EQ(6U, order.Size()); |
| 1101 EXPECT_EQ(order[ 0], TaskItem(ORDERERD, 1, true)); | 1035 EXPECT_EQ(order.Get(0), TaskItem(ORDERERD, 1, true)); |
| 1102 EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 1, false)); | 1036 EXPECT_EQ(order.Get(1), TaskItem(ORDERERD, 1, false)); |
| 1103 EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 2, true)); | 1037 EXPECT_EQ(order.Get(2), TaskItem(ORDERERD, 2, true)); |
| 1104 EXPECT_EQ(order[ 3], TaskItem(ORDERERD, 2, false)); | 1038 EXPECT_EQ(order.Get(3), TaskItem(ORDERERD, 2, false)); |
| 1105 EXPECT_EQ(order[ 4], TaskItem(QUITMESSAGELOOP, 3, true)); | 1039 EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true)); |
| 1106 EXPECT_EQ(order[ 5], TaskItem(QUITMESSAGELOOP, 3, false)); | 1040 EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false)); |
| 1107 } | 1041 } |
| 1108 | 1042 |
| 1109 // Tests that non nestable tasks don't run when there's code in the call stack. | 1043 // Tests that non nestable tasks don't run when there's code in the call stack. |
| 1110 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type, | 1044 void RunTest_NonNestableInNestedLoop(MessageLoop::Type message_loop_type, |
| 1111 bool use_delayed) { | 1045 bool use_delayed) { |
| 1112 MessageLoop loop(message_loop_type); | 1046 MessageLoop loop(message_loop_type); |
| 1113 | 1047 |
| 1114 TaskList order; | 1048 TaskList order; |
| 1115 | 1049 |
| 1116 MessageLoop::current()->PostTask(FROM_HERE, | 1050 MessageLoop::current()->PostClosure( |
| 1117 new TaskThatPumps(&order, 1)); | 1051 FROM_HERE, |
| 1118 Task* task = new OrderedTasks(&order, 2); | 1052 base::Bind(&FuncThatPumps, &order, 1)); |
| 1119 if (use_delayed) { | 1053 if (use_delayed) { |
| 1120 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, task, 1); | 1054 MessageLoop::current()->PostNonNestableDelayedClosure( |
| 1055 FROM_HERE, |
| 1056 base::Bind(&OrderedFunc, &order, 2), |
| 1057 1); |
| 1121 } else { | 1058 } else { |
| 1122 MessageLoop::current()->PostNonNestableTask(FROM_HERE, task); | 1059 MessageLoop::current()->PostNonNestableClosure( |
| 1060 FROM_HERE, |
| 1061 base::Bind(&OrderedFunc, &order, 2)); |
| 1123 } | 1062 } |
| 1124 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 3)); | 1063 MessageLoop::current()->PostClosure(FROM_HERE, |
| 1125 MessageLoop::current()->PostTask(FROM_HERE, new SleepTask(&order, 4, 50)); | 1064 base::Bind(&OrderedFunc, &order, 3)); |
| 1126 MessageLoop::current()->PostTask(FROM_HERE, new OrderedTasks(&order, 5)); | 1065 MessageLoop::current()->PostClosure(FROM_HERE, |
| 1127 Task* non_nestable_quit = new QuitTask(&order, 6); | 1066 base::Bind(&SleepFunc, &order, 4, 50)); |
| 1067 MessageLoop::current()->PostClosure(FROM_HERE, |
| 1068 base::Bind(&OrderedFunc, &order, 5)); |
| 1128 if (use_delayed) { | 1069 if (use_delayed) { |
| 1129 MessageLoop::current()->PostNonNestableDelayedTask(FROM_HERE, | 1070 MessageLoop::current()->PostNonNestableDelayedClosure( |
| 1130 non_nestable_quit, | 1071 FROM_HERE, |
| 1131 2); | 1072 base::Bind(&QuitFunc, &order, 6), |
| 1073 2); |
| 1132 } else { | 1074 } else { |
| 1133 MessageLoop::current()->PostNonNestableTask(FROM_HERE, non_nestable_quit); | 1075 MessageLoop::current()->PostNonNestableClosure( |
| 1076 FROM_HERE, |
| 1077 base::Bind(&QuitFunc, &order, 6)); |
| 1134 } | 1078 } |
| 1135 | 1079 |
| 1136 MessageLoop::current()->Run(); | 1080 MessageLoop::current()->Run(); |
| 1137 | 1081 |
| 1138 // FIFO order. | 1082 // FIFO order. |
| 1139 ASSERT_EQ(12U, order.size()); | 1083 ASSERT_EQ(12U, order.Size()); |
| 1140 EXPECT_EQ(order[ 0], TaskItem(PUMPS, 1, true)); | 1084 EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true)); |
| 1141 EXPECT_EQ(order[ 1], TaskItem(ORDERERD, 3, true)); | 1085 EXPECT_EQ(order.Get(1), TaskItem(ORDERERD, 3, true)); |
| 1142 EXPECT_EQ(order[ 2], TaskItem(ORDERERD, 3, false)); | 1086 EXPECT_EQ(order.Get(2), TaskItem(ORDERERD, 3, false)); |
| 1143 EXPECT_EQ(order[ 3], TaskItem(SLEEP, 4, true)); | 1087 EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true)); |
| 1144 EXPECT_EQ(order[ 4], TaskItem(SLEEP, 4, false)); | 1088 EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false)); |
| 1145 EXPECT_EQ(order[ 5], TaskItem(ORDERERD, 5, true)); | 1089 EXPECT_EQ(order.Get(5), TaskItem(ORDERERD, 5, true)); |
| 1146 EXPECT_EQ(order[ 6], TaskItem(ORDERERD, 5, false)); | 1090 EXPECT_EQ(order.Get(6), TaskItem(ORDERERD, 5, false)); |
| 1147 EXPECT_EQ(order[ 7], TaskItem(PUMPS, 1, false)); | 1091 EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false)); |
| 1148 EXPECT_EQ(order[ 8], TaskItem(ORDERERD, 2, true)); | 1092 EXPECT_EQ(order.Get(8), TaskItem(ORDERERD, 2, true)); |
| 1149 EXPECT_EQ(order[ 9], TaskItem(ORDERERD, 2, false)); | 1093 EXPECT_EQ(order.Get(9), TaskItem(ORDERERD, 2, false)); |
| 1150 EXPECT_EQ(order[10], TaskItem(QUITMESSAGELOOP, 6, true)); | 1094 EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true)); |
| 1151 EXPECT_EQ(order[11], TaskItem(QUITMESSAGELOOP, 6, false)); | 1095 EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false)); |
| 1152 } | 1096 } |
| 1153 | 1097 |
| 1154 #if defined(OS_WIN) | 1098 #if defined(OS_WIN) |
| 1155 | 1099 |
| 1156 class DispatcherImpl : public MessageLoopForUI::Dispatcher { | 1100 class DispatcherImpl : public MessageLoopForUI::Dispatcher { |
| 1157 public: | 1101 public: |
| 1158 DispatcherImpl() : dispatch_count_(0) {} | 1102 DispatcherImpl() : dispatch_count_(0) {} |
| 1159 | 1103 |
| 1160 virtual bool Dispatch(const MSG& msg) { | 1104 virtual bool Dispatch(const MSG& msg) { |
| 1161 ::TranslateMessage(&msg); | 1105 ::TranslateMessage(&msg); |
| 1162 ::DispatchMessage(&msg); | 1106 ::DispatchMessage(&msg); |
| 1163 // Do not count WM_TIMER since it is not what we post and it will cause | 1107 // Do not count WM_TIMER since it is not what we post and it will cause |
| 1164 // flakiness. | 1108 // flakiness. |
| 1165 if (msg.message != WM_TIMER) | 1109 if (msg.message != WM_TIMER) |
| 1166 ++dispatch_count_; | 1110 ++dispatch_count_; |
| 1167 // We treat WM_LBUTTONUP as the last message. | 1111 // We treat WM_LBUTTONUP as the last message. |
| 1168 return msg.message != WM_LBUTTONUP; | 1112 return msg.message != WM_LBUTTONUP; |
| 1169 } | 1113 } |
| 1170 | 1114 |
| 1171 int dispatch_count_; | 1115 int dispatch_count_; |
| 1172 }; | 1116 }; |
| 1173 | 1117 |
| 1118 void MouseDownUp() { |
| 1119 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0); |
| 1120 PostMessage(NULL, WM_LBUTTONUP, 'A', 0); |
| 1121 } |
| 1122 |
| 1174 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) { | 1123 void RunTest_Dispatcher(MessageLoop::Type message_loop_type) { |
| 1175 MessageLoop loop(message_loop_type); | 1124 MessageLoop loop(message_loop_type); |
| 1176 | 1125 |
| 1177 class MyTask : public Task { | 1126 MessageLoop::current()->PostDelayedClosure(FROM_HERE, |
| 1178 public: | 1127 base::Bind(&MouseDownUp), 100); |
| 1179 virtual void Run() { | |
| 1180 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0); | |
| 1181 PostMessage(NULL, WM_LBUTTONUP, 'A', 0); | |
| 1182 } | |
| 1183 }; | |
| 1184 Task* task = new MyTask(); | |
| 1185 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100); | |
| 1186 DispatcherImpl dispatcher; | 1128 DispatcherImpl dispatcher; |
| 1187 MessageLoopForUI::current()->Run(&dispatcher); | 1129 MessageLoopForUI::current()->Run(&dispatcher); |
| 1188 ASSERT_EQ(2, dispatcher.dispatch_count_); | 1130 ASSERT_EQ(2, dispatcher.dispatch_count_); |
| 1189 } | 1131 } |
| 1190 | 1132 |
| 1191 LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) { | 1133 LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) { |
| 1192 if (code == base::MessagePumpForUI::kMessageFilterCode) { | 1134 if (code == base::MessagePumpForUI::kMessageFilterCode) { |
| 1193 MSG* msg = reinterpret_cast<MSG*>(lparam); | 1135 MSG* msg = reinterpret_cast<MSG*>(lparam); |
| 1194 if (msg->message == WM_LBUTTONDOWN) | 1136 if (msg->message == WM_LBUTTONDOWN) |
| 1195 return TRUE; | 1137 return TRUE; |
| 1196 } | 1138 } |
| 1197 return FALSE; | 1139 return FALSE; |
| 1198 } | 1140 } |
| 1199 | 1141 |
| 1200 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) { | 1142 void RunTest_DispatcherWithMessageHook(MessageLoop::Type message_loop_type) { |
| 1201 MessageLoop loop(message_loop_type); | 1143 MessageLoop loop(message_loop_type); |
| 1202 | 1144 |
| 1203 class MyTask : public Task { | 1145 MessageLoop::current()->PostDelayedClosure(FROM_HERE, |
| 1204 public: | 1146 base::Bind(&MouseDownUp), 100); |
| 1205 virtual void Run() { | |
| 1206 PostMessage(NULL, WM_LBUTTONDOWN, 0, 0); | |
| 1207 PostMessage(NULL, WM_LBUTTONUP, 'A', 0); | |
| 1208 } | |
| 1209 }; | |
| 1210 Task* task = new MyTask(); | |
| 1211 MessageLoop::current()->PostDelayedTask(FROM_HERE, task, 100); | |
| 1212 HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER, | 1147 HHOOK msg_hook = SetWindowsHookEx(WH_MSGFILTER, |
| 1213 MsgFilterProc, | 1148 MsgFilterProc, |
| 1214 NULL, | 1149 NULL, |
| 1215 GetCurrentThreadId()); | 1150 GetCurrentThreadId()); |
| 1216 DispatcherImpl dispatcher; | 1151 DispatcherImpl dispatcher; |
| 1217 MessageLoopForUI::current()->Run(&dispatcher); | 1152 MessageLoopForUI::current()->Run(&dispatcher); |
| 1218 ASSERT_EQ(1, dispatcher.dispatch_count_); | 1153 ASSERT_EQ(1, dispatcher.dispatch_count_); |
| 1219 UnhookWindowsHookEx(msg_hook); | 1154 UnhookWindowsHookEx(msg_hook); |
| 1220 } | 1155 } |
| 1221 | 1156 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1264 DWORD bytes_transfered, DWORD error) { | 1199 DWORD bytes_transfered, DWORD error) { |
| 1265 ASSERT_TRUE(context == &context_); | 1200 ASSERT_TRUE(context == &context_); |
| 1266 ASSERT_TRUE(SetEvent(signal_)); | 1201 ASSERT_TRUE(SetEvent(signal_)); |
| 1267 } | 1202 } |
| 1268 | 1203 |
| 1269 void TestIOHandler::WaitForIO() { | 1204 void TestIOHandler::WaitForIO() { |
| 1270 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this)); | 1205 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(300, this)); |
| 1271 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this)); | 1206 EXPECT_TRUE(MessageLoopForIO::current()->WaitForIOCompletion(400, this)); |
| 1272 } | 1207 } |
| 1273 | 1208 |
| 1274 class IOHandlerTask : public Task { | |
| 1275 public: | |
| 1276 explicit IOHandlerTask(TestIOHandler* handler) : handler_(handler) {} | |
| 1277 virtual void Run() { | |
| 1278 handler_->Init(); | |
| 1279 } | |
| 1280 | |
| 1281 private: | |
| 1282 TestIOHandler* handler_; | |
| 1283 }; | |
| 1284 | |
| 1285 void RunTest_IOHandler() { | 1209 void RunTest_IOHandler() { |
| 1286 base::win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL)); | 1210 base::win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL)); |
| 1287 ASSERT_TRUE(callback_called.IsValid()); | 1211 ASSERT_TRUE(callback_called.IsValid()); |
| 1288 | 1212 |
| 1289 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe"; | 1213 const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe"; |
| 1290 base::win::ScopedHandle server( | 1214 base::win::ScopedHandle server( |
| 1291 CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL)); | 1215 CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL)); |
| 1292 ASSERT_TRUE(server.IsValid()); | 1216 ASSERT_TRUE(server.IsValid()); |
| 1293 | 1217 |
| 1294 Thread thread("IOHandler test"); | 1218 Thread thread("IOHandler test"); |
| 1295 Thread::Options options; | 1219 Thread::Options options; |
| 1296 options.message_loop_type = MessageLoop::TYPE_IO; | 1220 options.message_loop_type = MessageLoop::TYPE_IO; |
| 1297 ASSERT_TRUE(thread.StartWithOptions(options)); | 1221 ASSERT_TRUE(thread.StartWithOptions(options)); |
| 1298 | 1222 |
| 1299 MessageLoop* thread_loop = thread.message_loop(); | 1223 MessageLoop* thread_loop = thread.message_loop(); |
| 1300 ASSERT_TRUE(NULL != thread_loop); | 1224 ASSERT_TRUE(NULL != thread_loop); |
| 1301 | 1225 |
| 1302 TestIOHandler handler(kPipeName, callback_called, false); | 1226 TestIOHandler handler(kPipeName, callback_called, false); |
| 1303 IOHandlerTask* task = new IOHandlerTask(&handler); | 1227 thread_loop->PostClosure(FROM_HERE, base::Bind(&TestIOHandler::Init, |
| 1304 thread_loop->PostTask(FROM_HERE, task); | 1228 base::Unretained(&handler))); |
| 1305 Sleep(100); // Make sure the thread runs and sleeps for lack of work. | 1229 Sleep(100); // Make sure the thread runs and sleeps for lack of work. |
| 1306 | 1230 |
| 1307 const char buffer[] = "Hello there!"; | 1231 const char buffer[] = "Hello there!"; |
| 1308 DWORD written; | 1232 DWORD written; |
| 1309 EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL)); | 1233 EXPECT_TRUE(WriteFile(server, buffer, sizeof(buffer), &written, NULL)); |
| 1310 | 1234 |
| 1311 DWORD result = WaitForSingleObject(callback_called, 1000); | 1235 DWORD result = WaitForSingleObject(callback_called, 1000); |
| 1312 EXPECT_EQ(WAIT_OBJECT_0, result); | 1236 EXPECT_EQ(WAIT_OBJECT_0, result); |
| 1313 | 1237 |
| 1314 thread.Stop(); | 1238 thread.Stop(); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1334 Thread thread("IOHandler test"); | 1258 Thread thread("IOHandler test"); |
| 1335 Thread::Options options; | 1259 Thread::Options options; |
| 1336 options.message_loop_type = MessageLoop::TYPE_IO; | 1260 options.message_loop_type = MessageLoop::TYPE_IO; |
| 1337 ASSERT_TRUE(thread.StartWithOptions(options)); | 1261 ASSERT_TRUE(thread.StartWithOptions(options)); |
| 1338 | 1262 |
| 1339 MessageLoop* thread_loop = thread.message_loop(); | 1263 MessageLoop* thread_loop = thread.message_loop(); |
| 1340 ASSERT_TRUE(NULL != thread_loop); | 1264 ASSERT_TRUE(NULL != thread_loop); |
| 1341 | 1265 |
| 1342 TestIOHandler handler1(kPipeName1, callback1_called, false); | 1266 TestIOHandler handler1(kPipeName1, callback1_called, false); |
| 1343 TestIOHandler handler2(kPipeName2, callback2_called, true); | 1267 TestIOHandler handler2(kPipeName2, callback2_called, true); |
| 1344 IOHandlerTask* task1 = new IOHandlerTask(&handler1); | 1268 thread_loop->PostClosure(FROM_HERE, base::Bind(&TestIOHandler::Init, |
| 1345 IOHandlerTask* task2 = new IOHandlerTask(&handler2); | 1269 base::Unretained(&handler1))); |
| 1346 thread_loop->PostTask(FROM_HERE, task1); | 1270 // TODO(ajwong): Do we really need such long Sleeps in ths function? |
| 1347 Sleep(100); // Make sure the thread runs and sleeps for lack of work. | 1271 Sleep(100); // Make sure the thread runs and sleeps for lack of work. |
| 1348 thread_loop->PostTask(FROM_HERE, task2); | 1272 thread_loop->PostClosure(FROM_HERE, base::Bind(&TestIOHandler::Init, |
| 1273 base::Unretained(&handler2))); |
| 1349 Sleep(100); | 1274 Sleep(100); |
| 1350 | 1275 |
| 1351 // At this time handler1 is waiting to be called, and the thread is waiting | 1276 // At this time handler1 is waiting to be called, and the thread is waiting |
| 1352 // on the Init method of handler2, filtering only handler2 callbacks. | 1277 // on the Init method of handler2, filtering only handler2 callbacks. |
| 1353 | 1278 |
| 1354 const char buffer[] = "Hello there!"; | 1279 const char buffer[] = "Hello there!"; |
| 1355 DWORD written; | 1280 DWORD written; |
| 1356 EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL)); | 1281 EXPECT_TRUE(WriteFile(server1, buffer, sizeof(buffer), &written, NULL)); |
| 1357 Sleep(200); | 1282 Sleep(200); |
| 1358 EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) << | 1283 EXPECT_EQ(WAIT_TIMEOUT, WaitForSingleObject(callback1_called, 0)) << |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1375 // Each test is run against each type of MessageLoop. That way we are sure | 1300 // Each test is run against each type of MessageLoop. That way we are sure |
| 1376 // that message loops work properly in all configurations. Of course, in some | 1301 // that message loops work properly in all configurations. Of course, in some |
| 1377 // cases, a unit test may only be for a particular type of loop. | 1302 // cases, a unit test may only be for a particular type of loop. |
| 1378 | 1303 |
| 1379 TEST(MessageLoopTest, PostTask) { | 1304 TEST(MessageLoopTest, PostTask) { |
| 1380 RunTest_PostTask(MessageLoop::TYPE_DEFAULT); | 1305 RunTest_PostTask(MessageLoop::TYPE_DEFAULT); |
| 1381 RunTest_PostTask(MessageLoop::TYPE_UI); | 1306 RunTest_PostTask(MessageLoop::TYPE_UI); |
| 1382 RunTest_PostTask(MessageLoop::TYPE_IO); | 1307 RunTest_PostTask(MessageLoop::TYPE_IO); |
| 1383 } | 1308 } |
| 1384 | 1309 |
| 1385 TEST(MessageLoopTest, PostTask_SEH) { | 1310 TEST(MessageLoopTest, PostClosure) { |
| 1386 RunTest_PostTask_SEH(MessageLoop::TYPE_DEFAULT); | 1311 RunTest_PostClosure(MessageLoop::TYPE_DEFAULT); |
| 1387 RunTest_PostTask_SEH(MessageLoop::TYPE_UI); | 1312 RunTest_PostClosure(MessageLoop::TYPE_UI); |
| 1388 RunTest_PostTask_SEH(MessageLoop::TYPE_IO); | 1313 RunTest_PostClosure(MessageLoop::TYPE_IO); |
| 1389 } | 1314 } |
| 1390 | 1315 |
| 1391 TEST(MessageLoopTest, PostDelayedTask_Basic) { | 1316 TEST(MessageLoopTest, PostClosure_SEH) { |
| 1392 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_DEFAULT); | 1317 RunTest_PostClosure_SEH(MessageLoop::TYPE_DEFAULT); |
| 1393 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_UI); | 1318 RunTest_PostClosure_SEH(MessageLoop::TYPE_UI); |
| 1394 RunTest_PostDelayedTask_Basic(MessageLoop::TYPE_IO); | 1319 RunTest_PostClosure_SEH(MessageLoop::TYPE_IO); |
| 1395 } | 1320 } |
| 1396 | 1321 |
| 1397 TEST(MessageLoopTest, PostDelayedTask_InDelayOrder) { | 1322 TEST(MessageLoopTest, PostDelayedClosure_Basic) { |
| 1398 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_DEFAULT); | 1323 RunTest_PostDelayedClosure_Basic(MessageLoop::TYPE_DEFAULT); |
| 1399 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_UI); | 1324 RunTest_PostDelayedClosure_Basic(MessageLoop::TYPE_UI); |
| 1400 RunTest_PostDelayedTask_InDelayOrder(MessageLoop::TYPE_IO); | 1325 RunTest_PostDelayedClosure_Basic(MessageLoop::TYPE_IO); |
| 1401 } | 1326 } |
| 1402 | 1327 |
| 1403 TEST(MessageLoopTest, PostDelayedTask_InPostOrder) { | 1328 TEST(MessageLoopTest, PostDelayedClosure_InDelayOrder) { |
| 1404 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_DEFAULT); | 1329 RunTest_PostDelayedClosure_InDelayOrder(MessageLoop::TYPE_DEFAULT); |
| 1405 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_UI); | 1330 RunTest_PostDelayedClosure_InDelayOrder(MessageLoop::TYPE_UI); |
| 1406 RunTest_PostDelayedTask_InPostOrder(MessageLoop::TYPE_IO); | 1331 RunTest_PostDelayedClosure_InDelayOrder(MessageLoop::TYPE_IO); |
| 1407 } | 1332 } |
| 1408 | 1333 |
| 1409 TEST(MessageLoopTest, PostDelayedTask_InPostOrder_2) { | 1334 TEST(MessageLoopTest, PostDelayedClosure_InPostOrder) { |
| 1410 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_DEFAULT); | 1335 RunTest_PostDelayedClosure_InPostOrder(MessageLoop::TYPE_DEFAULT); |
| 1411 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_UI); | 1336 RunTest_PostDelayedClosure_InPostOrder(MessageLoop::TYPE_UI); |
| 1412 RunTest_PostDelayedTask_InPostOrder_2(MessageLoop::TYPE_IO); | 1337 RunTest_PostDelayedClosure_InPostOrder(MessageLoop::TYPE_IO); |
| 1413 } | 1338 } |
| 1414 | 1339 |
| 1415 TEST(MessageLoopTest, PostDelayedTask_InPostOrder_3) { | 1340 TEST(MessageLoopTest, PostDelayedClosure_InPostOrder_2) { |
| 1416 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_DEFAULT); | 1341 RunTest_PostDelayedClosure_InPostOrder_2(MessageLoop::TYPE_DEFAULT); |
| 1417 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_UI); | 1342 RunTest_PostDelayedClosure_InPostOrder_2(MessageLoop::TYPE_UI); |
| 1418 RunTest_PostDelayedTask_InPostOrder_3(MessageLoop::TYPE_IO); | 1343 RunTest_PostDelayedClosure_InPostOrder_2(MessageLoop::TYPE_IO); |
| 1419 } | 1344 } |
| 1420 | 1345 |
| 1421 TEST(MessageLoopTest, PostDelayedTask_SharedTimer) { | 1346 TEST(MessageLoopTest, PostDelayedClosure_InPostOrder_3) { |
| 1422 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_DEFAULT); | 1347 RunTest_PostDelayedClosure_InPostOrder_3(MessageLoop::TYPE_DEFAULT); |
| 1423 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_UI); | 1348 RunTest_PostDelayedClosure_InPostOrder_3(MessageLoop::TYPE_UI); |
| 1424 RunTest_PostDelayedTask_SharedTimer(MessageLoop::TYPE_IO); | 1349 RunTest_PostDelayedClosure_InPostOrder_3(MessageLoop::TYPE_IO); |
| 1350 } |
| 1351 |
| 1352 TEST(MessageLoopTest, PostDelayedClosure_SharedTimer) { |
| 1353 RunTest_PostDelayedClosure_SharedTimer(MessageLoop::TYPE_DEFAULT); |
| 1354 RunTest_PostDelayedClosure_SharedTimer(MessageLoop::TYPE_UI); |
| 1355 RunTest_PostDelayedClosure_SharedTimer(MessageLoop::TYPE_IO); |
| 1425 } | 1356 } |
| 1426 | 1357 |
| 1427 #if defined(OS_WIN) | 1358 #if defined(OS_WIN) |
| 1428 TEST(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) { | 1359 TEST(MessageLoopTest, PostDelayedClosure_SharedTimer_SubPump) { |
| 1429 RunTest_PostDelayedTask_SharedTimer_SubPump(); | 1360 RunTest_PostDelayedClosure_SharedTimer_SubPump(); |
| 1430 } | 1361 } |
| 1431 #endif | 1362 #endif |
| 1432 | 1363 |
| 1433 // TODO(darin): MessageLoop does not support deleting all tasks in the | 1364 // TODO(darin): MessageLoop does not support deleting all tasks in the |
| 1434 // destructor. | 1365 // destructor. |
| 1435 // Fails, http://crbug.com/50272. | 1366 // Fails, http://crbug.com/50272. |
| 1436 TEST(MessageLoopTest, FAILS_EnsureTaskDeletion) { | 1367 TEST(MessageLoopTest, FAILS_EnsureDeletion) { |
| 1437 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_DEFAULT); | 1368 RunTest_EnsureDeletion(MessageLoop::TYPE_DEFAULT); |
| 1438 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_UI); | 1369 RunTest_EnsureDeletion(MessageLoop::TYPE_UI); |
| 1439 RunTest_EnsureTaskDeletion(MessageLoop::TYPE_IO); | 1370 RunTest_EnsureDeletion(MessageLoop::TYPE_IO); |
| 1440 } | 1371 } |
| 1441 | 1372 |
| 1442 // TODO(darin): MessageLoop does not support deleting all tasks in the | 1373 // TODO(darin): MessageLoop does not support deleting all tasks in the |
| 1443 // destructor. | 1374 // destructor. |
| 1444 // Fails, http://crbug.com/50272. | 1375 // Fails, http://crbug.com/50272. |
| 1445 TEST(MessageLoopTest, FAILS_EnsureTaskDeletion_Chain) { | 1376 TEST(MessageLoopTest, FAILS_EnsureDeletion_Chain) { |
| 1446 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_DEFAULT); | 1377 RunTest_EnsureDeletion_Chain(MessageLoop::TYPE_DEFAULT); |
| 1447 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_UI); | 1378 RunTest_EnsureDeletion_Chain(MessageLoop::TYPE_UI); |
| 1448 RunTest_EnsureTaskDeletion_Chain(MessageLoop::TYPE_IO); | 1379 RunTest_EnsureDeletion_Chain(MessageLoop::TYPE_IO); |
| 1449 } | 1380 } |
| 1450 | 1381 |
| 1451 #if defined(OS_WIN) | 1382 #if defined(OS_WIN) |
| 1452 TEST(MessageLoopTest, Crasher) { | 1383 TEST(MessageLoopTest, Crasher) { |
| 1453 RunTest_Crasher(MessageLoop::TYPE_DEFAULT); | 1384 RunTest_Crasher(MessageLoop::TYPE_DEFAULT); |
| 1454 RunTest_Crasher(MessageLoop::TYPE_UI); | 1385 RunTest_Crasher(MessageLoop::TYPE_UI); |
| 1455 RunTest_Crasher(MessageLoop::TYPE_IO); | 1386 RunTest_Crasher(MessageLoop::TYPE_IO); |
| 1456 } | 1387 } |
| 1457 | 1388 |
| 1458 TEST(MessageLoopTest, CrasherNasty) { | 1389 TEST(MessageLoopTest, CrasherNasty) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1511 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, false); | 1442 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, false); |
| 1512 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, false); | 1443 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, false); |
| 1513 } | 1444 } |
| 1514 | 1445 |
| 1515 TEST(MessageLoopTest, NonNestableDelayedInNestedLoop) { | 1446 TEST(MessageLoopTest, NonNestableDelayedInNestedLoop) { |
| 1516 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, true); | 1447 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_DEFAULT, true); |
| 1517 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, true); | 1448 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_UI, true); |
| 1518 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true); | 1449 RunTest_NonNestableInNestedLoop(MessageLoop::TYPE_IO, true); |
| 1519 } | 1450 } |
| 1520 | 1451 |
| 1521 class DummyTask : public Task { | 1452 void PostNClosuresThenQuit(int posts_remaining) { |
| 1453 if (posts_remaining > 1) { |
| 1454 MessageLoop::current()->PostClosure( |
| 1455 FROM_HERE, |
| 1456 base::Bind(&PostNClosuresThenQuit, posts_remaining - 1)); |
| 1457 } else { |
| 1458 MessageLoop::current()->Quit(); |
| 1459 } |
| 1460 } |
| 1461 |
| 1462 class DummyClosureObserver : public MessageLoop::ClosureObserver { |
| 1522 public: | 1463 public: |
| 1523 explicit DummyTask(int num_tasks) : num_tasks_(num_tasks) {} | 1464 explicit DummyClosureObserver(int num_closures) |
| 1465 : num_closures_started_(0), |
| 1466 num_closures_processed_(0), |
| 1467 num_closures_(num_closures) {} |
| 1524 | 1468 |
| 1525 virtual void Run() { | 1469 virtual ~DummyClosureObserver() {} |
| 1526 if (num_tasks_ > 1) { | 1470 |
| 1527 MessageLoop::current()->PostTask( | 1471 virtual void WillProcessClosure(TimeTicks time_posted) OVERRIDE { |
| 1528 FROM_HERE, | 1472 num_closures_started_++; |
| 1529 new DummyTask(num_tasks_ - 1)); | 1473 EXPECT_TRUE(time_posted != TimeTicks()); |
| 1530 } else { | 1474 EXPECT_LE(num_closures_started_, num_closures_); |
| 1531 MessageLoop::current()->Quit(); | 1475 EXPECT_EQ(num_closures_started_, num_closures_processed_ + 1); |
| 1532 } | |
| 1533 } | 1476 } |
| 1534 | 1477 |
| 1478 virtual void DidProcessClosure(TimeTicks time_posted) OVERRIDE { |
| 1479 num_closures_processed_++; |
| 1480 EXPECT_TRUE(time_posted != TimeTicks()); |
| 1481 EXPECT_LE(num_closures_started_, num_closures_); |
| 1482 EXPECT_EQ(num_closures_started_, num_closures_processed_); |
| 1483 } |
| 1484 |
| 1485 int num_closures_started() const { return num_closures_started_; } |
| 1486 int num_closures_processed() const { return num_closures_processed_; } |
| 1487 |
| 1535 private: | 1488 private: |
| 1536 const int num_tasks_; | 1489 int num_closures_started_; |
| 1490 int num_closures_processed_; |
| 1491 const int num_closures_; |
| 1492 |
| 1493 DISALLOW_COPY_AND_ASSIGN(DummyClosureObserver); |
| 1537 }; | 1494 }; |
| 1538 | 1495 |
| 1539 class DummyTaskObserver : public MessageLoop::TaskObserver { | 1496 TEST(MessageLoopTest, ClosureObserver) { |
| 1540 public: | 1497 const int kNumPosts = 6; |
| 1541 explicit DummyTaskObserver(int num_tasks) | 1498 DummyClosureObserver observer(kNumPosts); |
| 1542 : num_tasks_started_(0), | |
| 1543 num_tasks_processed_(0), | |
| 1544 num_tasks_(num_tasks) {} | |
| 1545 | |
| 1546 virtual ~DummyTaskObserver() {} | |
| 1547 | |
| 1548 virtual void WillProcessTask(const Task* task) { | |
| 1549 num_tasks_started_++; | |
| 1550 EXPECT_TRUE(task != NULL); | |
| 1551 EXPECT_LE(num_tasks_started_, num_tasks_); | |
| 1552 EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1); | |
| 1553 } | |
| 1554 | |
| 1555 virtual void DidProcessTask(const Task* task) { | |
| 1556 num_tasks_processed_++; | |
| 1557 EXPECT_TRUE(task != NULL); | |
| 1558 EXPECT_LE(num_tasks_started_, num_tasks_); | |
| 1559 EXPECT_EQ(num_tasks_started_, num_tasks_processed_); | |
| 1560 } | |
| 1561 | |
| 1562 int num_tasks_started() const { return num_tasks_started_; } | |
| 1563 int num_tasks_processed() const { return num_tasks_processed_; } | |
| 1564 | |
| 1565 private: | |
| 1566 int num_tasks_started_; | |
| 1567 int num_tasks_processed_; | |
| 1568 const int num_tasks_; | |
| 1569 | |
| 1570 DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver); | |
| 1571 }; | |
| 1572 | |
| 1573 TEST(MessageLoopTest, TaskObserver) { | |
| 1574 const int kNumTasks = 6; | |
| 1575 DummyTaskObserver observer(kNumTasks); | |
| 1576 | 1499 |
| 1577 MessageLoop loop; | 1500 MessageLoop loop; |
| 1578 loop.AddTaskObserver(&observer); | 1501 loop.AddClosureObserver(&observer); |
| 1579 loop.PostTask(FROM_HERE, new DummyTask(kNumTasks)); | 1502 loop.PostClosure(FROM_HERE, base::Bind(&PostNClosuresThenQuit, kNumPosts)); |
| 1580 loop.Run(); | 1503 loop.Run(); |
| 1581 loop.RemoveTaskObserver(&observer); | 1504 loop.RemoveClosureObserver(&observer); |
| 1582 | 1505 |
| 1583 EXPECT_EQ(kNumTasks, observer.num_tasks_started()); | 1506 EXPECT_EQ(kNumPosts, observer.num_closures_started()); |
| 1584 EXPECT_EQ(kNumTasks, observer.num_tasks_processed()); | 1507 EXPECT_EQ(kNumPosts, observer.num_closures_processed()); |
| 1585 } | 1508 } |
| 1586 | 1509 |
| 1587 #if defined(OS_WIN) | 1510 #if defined(OS_WIN) |
| 1588 TEST(MessageLoopTest, Dispatcher) { | 1511 TEST(MessageLoopTest, Dispatcher) { |
| 1589 // This test requires a UI loop | 1512 // This test requires a UI loop |
| 1590 RunTest_Dispatcher(MessageLoop::TYPE_UI); | 1513 RunTest_Dispatcher(MessageLoop::TYPE_UI); |
| 1591 } | 1514 } |
| 1592 | 1515 |
| 1593 TEST(MessageLoopTest, DispatcherWithMessageHook) { | 1516 TEST(MessageLoopTest, DispatcherWithMessageHook) { |
| 1594 // This test requires a UI loop | 1517 // This test requires a UI loop |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1605 | 1528 |
| 1606 TEST(MessageLoopTest, HighResolutionTimer) { | 1529 TEST(MessageLoopTest, HighResolutionTimer) { |
| 1607 MessageLoop loop; | 1530 MessageLoop loop; |
| 1608 | 1531 |
| 1609 const int kFastTimerMs = 5; | 1532 const int kFastTimerMs = 5; |
| 1610 const int kSlowTimerMs = 100; | 1533 const int kSlowTimerMs = 100; |
| 1611 | 1534 |
| 1612 EXPECT_FALSE(loop.high_resolution_timers_enabled()); | 1535 EXPECT_FALSE(loop.high_resolution_timers_enabled()); |
| 1613 | 1536 |
| 1614 // Post a fast task to enable the high resolution timers. | 1537 // Post a fast task to enable the high resolution timers. |
| 1615 loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kFastTimerMs); | 1538 loop.PostDelayedClosure(FROM_HERE, base::Bind(&PostNClosuresThenQuit, 1), |
| 1539 kFastTimerMs); |
| 1616 loop.Run(); | 1540 loop.Run(); |
| 1617 EXPECT_TRUE(loop.high_resolution_timers_enabled()); | 1541 EXPECT_TRUE(loop.high_resolution_timers_enabled()); |
| 1618 | 1542 |
| 1619 // Post a slow task and verify high resolution timers | 1543 // Post a slow task and verify high resolution timers |
| 1620 // are still enabled. | 1544 // are still enabled. |
| 1621 loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs); | 1545 loop.PostDelayedClosure(FROM_HERE, base::Bind(&PostNClosuresThenQuit, 1), |
| 1546 kSlowTimerMs); |
| 1622 loop.Run(); | 1547 loop.Run(); |
| 1623 EXPECT_TRUE(loop.high_resolution_timers_enabled()); | 1548 EXPECT_TRUE(loop.high_resolution_timers_enabled()); |
| 1624 | 1549 |
| 1625 // Wait for a while so that high-resolution mode elapses. | 1550 // Wait for a while so that high-resolution mode elapses. |
| 1626 Sleep(MessageLoop::kHighResolutionTimerModeLeaseTimeMs); | 1551 Sleep(MessageLoop::kHighResolutionTimerModeLeaseTimeMs); |
| 1627 | 1552 |
| 1628 // Post a slow task to disable the high resolution timers. | 1553 // Post a slow task to disable the high resolution timers. |
| 1629 loop.PostDelayedTask(FROM_HERE, new DummyTask(1), kSlowTimerMs); | 1554 loop.PostDelayedClosure(FROM_HERE, base::Bind(&PostNClosuresThenQuit, 1), |
| 1555 kSlowTimerMs); |
| 1630 loop.Run(); | 1556 loop.Run(); |
| 1631 EXPECT_FALSE(loop.high_resolution_timers_enabled()); | 1557 EXPECT_FALSE(loop.high_resolution_timers_enabled()); |
| 1632 } | 1558 } |
| 1633 | 1559 |
| 1634 #endif // defined(OS_WIN) | 1560 #endif // defined(OS_WIN) |
| 1635 | 1561 |
| 1636 #if defined(OS_POSIX) && !defined(OS_NACL) | 1562 #if defined(OS_POSIX) && !defined(OS_NACL) |
| 1637 | 1563 |
| 1638 namespace { | 1564 namespace { |
| 1639 | 1565 |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1699 PLOG(ERROR) << "close"; | 1625 PLOG(ERROR) << "close"; |
| 1700 if (HANDLE_EINTR(close(pipefds[1])) < 0) | 1626 if (HANDLE_EINTR(close(pipefds[1])) < 0) |
| 1701 PLOG(ERROR) << "close"; | 1627 PLOG(ERROR) << "close"; |
| 1702 } | 1628 } |
| 1703 | 1629 |
| 1704 } // namespace | 1630 } // namespace |
| 1705 | 1631 |
| 1706 #endif // defined(OS_POSIX) && !defined(OS_NACL) | 1632 #endif // defined(OS_POSIX) && !defined(OS_NACL) |
| 1707 | 1633 |
| 1708 namespace { | 1634 namespace { |
| 1709 class RunAtDestructionTask : public Task { | 1635 class DestructionObserverProbe : |
| 1636 public base::RefCounted<DestructionObserverProbe> { |
| 1710 public: | 1637 public: |
| 1711 RunAtDestructionTask(bool* task_destroyed, bool* destruction_observer_called) | 1638 DestructionObserverProbe(bool* task_destroyed, |
| 1639 bool* destruction_observer_called) |
| 1712 : task_destroyed_(task_destroyed), | 1640 : task_destroyed_(task_destroyed), |
| 1713 destruction_observer_called_(destruction_observer_called) { | 1641 destruction_observer_called_(destruction_observer_called) { |
| 1714 } | 1642 } |
| 1715 ~RunAtDestructionTask() { | 1643 virtual ~DestructionObserverProbe() { |
| 1716 EXPECT_FALSE(*destruction_observer_called_); | 1644 EXPECT_FALSE(*destruction_observer_called_); |
| 1717 *task_destroyed_ = true; | 1645 *task_destroyed_ = true; |
| 1718 } | 1646 } |
| 1719 virtual void Run() { | 1647 virtual void Run() { |
| 1720 // This task should never run. | 1648 // This task should never run. |
| 1721 ADD_FAILURE(); | 1649 ADD_FAILURE(); |
| 1722 } | 1650 } |
| 1723 private: | 1651 private: |
| 1724 bool* task_destroyed_; | 1652 bool* task_destroyed_; |
| 1725 bool* destruction_observer_called_; | 1653 bool* destruction_observer_called_; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1751 // Verify that the destruction observer gets called at the very end (after | 1679 // Verify that the destruction observer gets called at the very end (after |
| 1752 // all the pending tasks have been destroyed). | 1680 // all the pending tasks have been destroyed). |
| 1753 MessageLoop* loop = new MessageLoop; | 1681 MessageLoop* loop = new MessageLoop; |
| 1754 const int kDelayMS = 100; | 1682 const int kDelayMS = 100; |
| 1755 | 1683 |
| 1756 bool task_destroyed = false; | 1684 bool task_destroyed = false; |
| 1757 bool destruction_observer_called = false; | 1685 bool destruction_observer_called = false; |
| 1758 | 1686 |
| 1759 MLDestructionObserver observer(&task_destroyed, &destruction_observer_called); | 1687 MLDestructionObserver observer(&task_destroyed, &destruction_observer_called); |
| 1760 loop->AddDestructionObserver(&observer); | 1688 loop->AddDestructionObserver(&observer); |
| 1761 loop->PostDelayedTask( | 1689 loop->PostDelayedClosure( |
| 1762 FROM_HERE, | 1690 FROM_HERE, |
| 1763 new RunAtDestructionTask(&task_destroyed, &destruction_observer_called), | 1691 base::Bind(&DestructionObserverProbe::Run, |
| 1692 new DestructionObserverProbe(&task_destroyed, |
| 1693 &destruction_observer_called)), |
| 1764 kDelayMS); | 1694 kDelayMS); |
| 1765 delete loop; | 1695 delete loop; |
| 1766 EXPECT_TRUE(observer.task_destroyed_before_message_loop()); | 1696 EXPECT_TRUE(observer.task_destroyed_before_message_loop()); |
| 1767 // The task should have been destroyed when we deleted the loop. | 1697 // The task should have been destroyed when we deleted the loop. |
| 1768 EXPECT_TRUE(task_destroyed); | 1698 EXPECT_TRUE(task_destroyed); |
| 1769 EXPECT_TRUE(destruction_observer_called); | 1699 EXPECT_TRUE(destruction_observer_called); |
| 1770 } | 1700 } |
| OLD | NEW |