1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "mojo/common/handle_watcher.h" 6 7 #include <string> 8 9 #include "base/at_exit.h" 10 #include "base/auto_reset.h" 11 #include "base/bind.h" 12 #include "base/memory/scoped_vector.h" 13 #include "base/run_loop.h" 14 #include "base/test/simple_test_tick_clock.h" 15 #include "base/threading/thread.h" 16 #include "mojo/common/message_pump_mojo.h" 17 #include "mojo/common/time_helper.h" 18 #include "mojo/public/cpp/system/core.h" 19 #include "mojo/public/cpp/test_support/test_utils.h" 20 #include "testing/gtest/include/gtest/gtest.h" 21 22 namespace mojo { 23 namespace common { 24 namespace test { 25 26 enum MessageLoopConfig { 27 MESSAGE_LOOP_CONFIG_DEFAULT = 0, 28 MESSAGE_LOOP_CONFIG_MOJO = 1 29 }; 30 31 void ObserveCallback(bool* was_signaled, 32 MojoResult* result_observed, 33 MojoResult result) { 34 *was_signaled = true; 35 *result_observed = result; 36 } 37 38 void RunUntilIdle() { 39 base::RunLoop run_loop; 40 run_loop.RunUntilIdle(); 41 } 42 43 void DeleteWatcherAndForwardResult( 44 HandleWatcher* watcher, 45 base::Callback<void(MojoResult)> next_callback, 46 MojoResult result) { 47 delete watcher; 48 next_callback.Run(result); 49 } 50 51 scoped_ptr<base::MessageLoop> CreateMessageLoop(MessageLoopConfig config) { 52 scoped_ptr<base::MessageLoop> loop; 53 if (config == MESSAGE_LOOP_CONFIG_DEFAULT) 54 loop.reset(new base::MessageLoop()); 55 else 56 loop.reset(new base::MessageLoop(MessagePumpMojo::Create())); 57 return loop.Pass(); 58 } 59 60 // Helper class to manage the callback and running the message loop waiting for 61 // message to be received. Typical usage is something like: 62 // Schedule callback returned from GetCallback(). 63 // RunUntilGotCallback(); 64 // EXPECT_TRUE(got_callback()); 65 // clear_callback(); 66 class CallbackHelper { 67 public: 68 CallbackHelper() 69 : got_callback_(false), 70 run_loop_(NULL), 71 weak_factory_(this) {} 72 ~CallbackHelper() {} 73 74 // See description above |got_callback_|. 75 bool got_callback() const { return got_callback_; } 76 void clear_callback() { got_callback_ = false; } 77 78 // Runs the current MessageLoop until the callback returned from GetCallback() 79 // is notified. 80 void RunUntilGotCallback() { 81 ASSERT_TRUE(run_loop_ == NULL); 82 base::RunLoop run_loop; 83 base::AutoReset<base::RunLoop*> reseter(&run_loop_, &run_loop); 84 run_loop.Run(); 85 } 86 87 base::Callback<void(MojoResult)> GetCallback() { 88 return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr()); 89 } 90 91 void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) { 92 StartWithCallback(watcher, handle, GetCallback()); 93 } 94 95 void StartWithCallback(HandleWatcher* watcher, 96 const MessagePipeHandle& handle, 97 const base::Callback<void(MojoResult)>& callback) { 98 watcher->Start(handle, MOJO_HANDLE_SIGNAL_READABLE, 99 MOJO_DEADLINE_INDEFINITE, callback); 100 } 101 102 private: 103 void OnCallback(MojoResult result) { 104 got_callback_ = true; 105 if (run_loop_) 106 run_loop_->Quit(); 107 } 108 109 // Set to true when the callback is called. 110 bool got_callback_; 111 112 // If non-NULL we're in RunUntilGotCallback(). 113 base::RunLoop* run_loop_; 114 115 base::WeakPtrFactory<CallbackHelper> weak_factory_; 116 117 private: 118 DISALLOW_COPY_AND_ASSIGN(CallbackHelper); 119 }; 120 121 class HandleWatcherTest : public testing::TestWithParam<MessageLoopConfig> { 122 public: 123 HandleWatcherTest() : message_loop_(CreateMessageLoop(GetParam())) {} 124 virtual ~HandleWatcherTest() { 125 test::SetTickClockForTest(NULL); 126 } 127 128 protected: 129 void TearDownMessageLoop() { 130 message_loop_.reset(); 131 } 132 133 void InstallTickClock() { 134 test::SetTickClockForTest(&tick_clock_); 135 } 136 137 base::SimpleTestTickClock tick_clock_; 138 139 private: 140 base::ShadowingAtExitManager at_exit_; 141 scoped_ptr<base::MessageLoop> message_loop_; 142 143 DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest); 144 }; 145 146 INSTANTIATE_TEST_CASE_P( 147 MultipleMessageLoopConfigs, HandleWatcherTest, 148 testing::Values(MESSAGE_LOOP_CONFIG_DEFAULT, MESSAGE_LOOP_CONFIG_MOJO)); 149 150 // Trivial test case with a single handle to watch. 151 TEST_P(HandleWatcherTest, SingleHandler) { 152 MessagePipe test_pipe; 153 ASSERT_TRUE(test_pipe.handle0.is_valid()); 154 CallbackHelper callback_helper; 155 HandleWatcher watcher; 156 callback_helper.Start(&watcher, test_pipe.handle0.get()); 157 RunUntilIdle(); 158 EXPECT_FALSE(callback_helper.got_callback()); 159 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), 160 std::string())); 161 callback_helper.RunUntilGotCallback(); 162 EXPECT_TRUE(callback_helper.got_callback()); 163 } 164 165 // Creates three handles and notfies them in reverse order ensuring each one is 166 // notified appropriately. 167 TEST_P(HandleWatcherTest, ThreeHandles) { 168 MessagePipe test_pipe1; 169 MessagePipe test_pipe2; 170 MessagePipe test_pipe3; 171 CallbackHelper callback_helper1; 172 CallbackHelper callback_helper2; 173 CallbackHelper callback_helper3; 174 ASSERT_TRUE(test_pipe1.handle0.is_valid()); 175 ASSERT_TRUE(test_pipe2.handle0.is_valid()); 176 ASSERT_TRUE(test_pipe3.handle0.is_valid()); 177 178 HandleWatcher watcher1; 179 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 180 RunUntilIdle(); 181 EXPECT_FALSE(callback_helper1.got_callback()); 182 EXPECT_FALSE(callback_helper2.got_callback()); 183 EXPECT_FALSE(callback_helper3.got_callback()); 184 185 HandleWatcher watcher2; 186 callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); 187 RunUntilIdle(); 188 EXPECT_FALSE(callback_helper1.got_callback()); 189 EXPECT_FALSE(callback_helper2.got_callback()); 190 EXPECT_FALSE(callback_helper3.got_callback()); 191 192 HandleWatcher watcher3; 193 callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); 194 RunUntilIdle(); 195 EXPECT_FALSE(callback_helper1.got_callback()); 196 EXPECT_FALSE(callback_helper2.got_callback()); 197 EXPECT_FALSE(callback_helper3.got_callback()); 198 199 // Write to 3 and make sure it's notified. 200 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), 201 std::string())); 202 callback_helper3.RunUntilGotCallback(); 203 EXPECT_FALSE(callback_helper1.got_callback()); 204 EXPECT_FALSE(callback_helper2.got_callback()); 205 EXPECT_TRUE(callback_helper3.got_callback()); 206 callback_helper3.clear_callback(); 207 208 // Write to 1 and 3. Only 1 should be notified since 3 was is no longer 209 // running. 210 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 211 std::string())); 212 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), 213 std::string())); 214 callback_helper1.RunUntilGotCallback(); 215 EXPECT_TRUE(callback_helper1.got_callback()); 216 EXPECT_FALSE(callback_helper2.got_callback()); 217 EXPECT_FALSE(callback_helper3.got_callback()); 218 callback_helper1.clear_callback(); 219 220 // Write to 1 and 2. Only 2 should be notified (since 1 was already notified). 221 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 222 std::string())); 223 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), 224 std::string())); 225 callback_helper2.RunUntilGotCallback(); 226 EXPECT_FALSE(callback_helper1.got_callback()); 227 EXPECT_TRUE(callback_helper2.got_callback()); 228 EXPECT_FALSE(callback_helper3.got_callback()); 229 } 230 231 // Verifies Start() invoked a second time works. 232 TEST_P(HandleWatcherTest, Restart) { 233 MessagePipe test_pipe1; 234 MessagePipe test_pipe2; 235 CallbackHelper callback_helper1; 236 CallbackHelper callback_helper2; 237 ASSERT_TRUE(test_pipe1.handle0.is_valid()); 238 ASSERT_TRUE(test_pipe2.handle0.is_valid()); 239 240 HandleWatcher watcher1; 241 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 242 RunUntilIdle(); 243 EXPECT_FALSE(callback_helper1.got_callback()); 244 EXPECT_FALSE(callback_helper2.got_callback()); 245 246 HandleWatcher watcher2; 247 callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); 248 RunUntilIdle(); 249 EXPECT_FALSE(callback_helper1.got_callback()); 250 EXPECT_FALSE(callback_helper2.got_callback()); 251 252 // Write to 1 and make sure it's notified. 253 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 254 std::string())); 255 callback_helper1.RunUntilGotCallback(); 256 EXPECT_TRUE(callback_helper1.got_callback()); 257 EXPECT_FALSE(callback_helper2.got_callback()); 258 callback_helper1.clear_callback(); 259 EXPECT_TRUE(mojo::test::DiscardMessage(test_pipe1.handle0.get())); 260 261 // Write to 2 and make sure it's notified. 262 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), 263 std::string())); 264 callback_helper2.RunUntilGotCallback(); 265 EXPECT_FALSE(callback_helper1.got_callback()); 266 EXPECT_TRUE(callback_helper2.got_callback()); 267 callback_helper2.clear_callback(); 268 269 // Listen on 1 again. 270 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 271 RunUntilIdle(); 272 EXPECT_FALSE(callback_helper1.got_callback()); 273 EXPECT_FALSE(callback_helper2.got_callback()); 274 275 // Write to 1 and make sure it's notified. 276 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 277 std::string())); 278 callback_helper1.RunUntilGotCallback(); 279 EXPECT_TRUE(callback_helper1.got_callback()); 280 EXPECT_FALSE(callback_helper2.got_callback()); 281 } 282 283 // Verifies deadline is honored. 284 TEST_P(HandleWatcherTest, Deadline) { 285 InstallTickClock(); 286 287 MessagePipe test_pipe1; 288 MessagePipe test_pipe2; 289 MessagePipe test_pipe3; 290 CallbackHelper callback_helper1; 291 CallbackHelper callback_helper2; 292 CallbackHelper callback_helper3; 293 ASSERT_TRUE(test_pipe1.handle0.is_valid()); 294 ASSERT_TRUE(test_pipe2.handle0.is_valid()); 295 ASSERT_TRUE(test_pipe3.handle0.is_valid()); 296 297 // Add a watcher with an infinite timeout. 298 HandleWatcher watcher1; 299 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 300 RunUntilIdle(); 301 EXPECT_FALSE(callback_helper1.got_callback()); 302 EXPECT_FALSE(callback_helper2.got_callback()); 303 EXPECT_FALSE(callback_helper3.got_callback()); 304 305 // Add another watcher wth a timeout of 500 microseconds. 306 HandleWatcher watcher2; 307 watcher2.Start(test_pipe2.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 500, 308 callback_helper2.GetCallback()); 309 RunUntilIdle(); 310 EXPECT_FALSE(callback_helper1.got_callback()); 311 EXPECT_FALSE(callback_helper2.got_callback()); 312 EXPECT_FALSE(callback_helper3.got_callback()); 313 314 // Advance the clock passed the deadline. We also have to start another 315 // watcher to wake up the background thread. 316 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(501)); 317 318 HandleWatcher watcher3; 319 callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); 320 321 callback_helper2.RunUntilGotCallback(); 322 EXPECT_FALSE(callback_helper1.got_callback()); 323 EXPECT_TRUE(callback_helper2.got_callback()); 324 EXPECT_FALSE(callback_helper3.got_callback()); 325 } 326 327 TEST_P(HandleWatcherTest, DeleteInCallback) { 328 MessagePipe test_pipe; 329 CallbackHelper callback_helper; 330 331 HandleWatcher* watcher = new HandleWatcher(); 332 callback_helper.StartWithCallback(watcher, test_pipe.handle1.get(), 333 base::Bind(&DeleteWatcherAndForwardResult, 334 watcher, 335 callback_helper.GetCallback())); 336 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle0.get(), 337 std::string())); 338 callback_helper.RunUntilGotCallback(); 339 EXPECT_TRUE(callback_helper.got_callback()); 340 } 341 342 TEST_P(HandleWatcherTest, AbortedOnMessageLoopDestruction) { 343 bool was_signaled = false; 344 MojoResult result = MOJO_RESULT_OK; 345 346 MessagePipe pipe; 347 HandleWatcher watcher; 348 watcher.Start(pipe.handle0.get(), 349 MOJO_HANDLE_SIGNAL_READABLE, 350 MOJO_DEADLINE_INDEFINITE, 351 base::Bind(&ObserveCallback, &was_signaled, &result)); 352 353 // Now, let the MessageLoop get torn down. We expect our callback to run. 354 TearDownMessageLoop(); 355 356 EXPECT_TRUE(was_signaled); 357 EXPECT_EQ(MOJO_RESULT_ABORTED, result); 358 } 359 360 void NeverReached(MojoResult result) { 361 FAIL() << "Callback should never be invoked " << result; 362 } 363 364 // Called on the main thread when a thread is done. Decrements |active_count| 365 // and if |active_count| is zero quits |run_loop|. 366 void StressThreadDone(base::RunLoop* run_loop, int* active_count) { 367 (*active_count)--; 368 EXPECT_GE(*active_count, 0); 369 if (*active_count == 0) 370 run_loop->Quit(); 371 } 372 373 // See description of StressTest. This is called on the background thread. 374 // |count| is the number of HandleWatchers to create. |active_count| is the 375 // number of outstanding threads, |task_runner| the task runner for the main 376 // thread and |run_loop| the run loop that should be quit when there are no more 377 // threads running. When done StressThreadDone() is invoked on the main thread. 378 // |active_count| and |run_loop| should only be used on the main thread. 379 void RunStressTest(int count, 380 scoped_refptr<base::TaskRunner> task_runner, 381 base::RunLoop* run_loop, 382 int* active_count) { 383 struct TestData { 384 MessagePipe pipe; 385 HandleWatcher watcher; 386 }; 387 ScopedVector<TestData> data_vector; 388 for (int i = 0; i < count; ++i) { 389 if (i % 20 == 0) { 390 // Every so often we wait. This results in some level of thread balancing 391 // as well as making sure HandleWatcher has time to actually start some 392 // watches. 393 MessagePipe test_pipe; 394 ASSERT_TRUE(test_pipe.handle0.is_valid()); 395 CallbackHelper callback_helper; 396 HandleWatcher watcher; 397 callback_helper.Start(&watcher, test_pipe.handle0.get()); 398 RunUntilIdle(); 399 EXPECT_FALSE(callback_helper.got_callback()); 400 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), 401 std::string())); 402 base::MessageLoop::ScopedNestableTaskAllower scoper( 403 base::MessageLoop::current()); 404 callback_helper.RunUntilGotCallback(); 405 EXPECT_TRUE(callback_helper.got_callback()); 406 } else { 407 scoped_ptr<TestData> test_data(new TestData); 408 ASSERT_TRUE(test_data->pipe.handle0.is_valid()); 409 test_data->watcher.Start(test_data->pipe.handle0.get(), 410 MOJO_HANDLE_SIGNAL_READABLE, 411 MOJO_DEADLINE_INDEFINITE, 412 base::Bind(&NeverReached)); 413 data_vector.push_back(test_data.release()); 414 } 415 if (i % 15 == 0) 416 data_vector.clear(); 417 } 418 task_runner->PostTask(FROM_HERE, 419 base::Bind(&StressThreadDone, run_loop, 420 active_count)); 421 } 422 423 // This test is meant to stress HandleWatcher. It uses from various threads 424 // repeatedly starting and stopping watches. It spins up kThreadCount 425 // threads. Each thread creates kWatchCount watches. Every so often each thread 426 // writes to a pipe and waits for the response. 427 TEST(HandleWatcherCleanEnvironmentTest, StressTest) { 428 #if defined(NDEBUG) 429 const int kThreadCount = 15; 430 const int kWatchCount = 400; 431 #else 432 const int kThreadCount = 10; 433 const int kWatchCount = 250; 434 #endif 435 436 base::ShadowingAtExitManager at_exit; 437 base::MessageLoop message_loop; 438 base::RunLoop run_loop; 439 ScopedVector<base::Thread> threads; 440 int threads_active_counter = kThreadCount; 441 // Starts the threads first and then post the task in hopes of having more 442 // threads running at once. 443 for (int i = 0; i < kThreadCount; ++i) { 444 scoped_ptr<base::Thread> thread(new base::Thread("test thread")); 445 if (i % 2) { 446 base::Thread::Options thread_options; 447 thread_options.message_pump_factory = 448 base::Bind(&MessagePumpMojo::Create); 449 thread->StartWithOptions(thread_options); 450 } else { 451 thread->Start(); 452 } 453 threads.push_back(thread.release()); 454 } 455 for (int i = 0; i < kThreadCount; ++i) { 456 threads[i]->task_runner()->PostTask( 457 FROM_HERE, base::Bind(&RunStressTest, kWatchCount, 458 message_loop.task_runner(), 459 &run_loop, &threads_active_counter)); 460 } 461 run_loop.Run(); 462 ASSERT_EQ(0, threads_active_counter); 463 } 464 465 } // namespace test 466 } // namespace common 467 } // namespace mojo 468