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/run_loop.h" 13 #include "base/test/simple_test_tick_clock.h" 14 #include "mojo/common/time_helper.h" 15 #include "mojo/public/cpp/system/core.h" 16 #include "mojo/public/cpp/test_support/test_utils.h" 17 #include "testing/gtest/include/gtest/gtest.h" 18 19 namespace mojo { 20 namespace common { 21 namespace test { 22 23 void ObserveCallback(bool* was_signaled, 24 MojoResult* result_observed, 25 MojoResult result) { 26 *was_signaled = true; 27 *result_observed = result; 28 } 29 30 void RunUntilIdle() { 31 base::RunLoop run_loop; 32 run_loop.RunUntilIdle(); 33 } 34 35 void DeleteWatcherAndForwardResult( 36 HandleWatcher* watcher, 37 base::Callback<void(MojoResult)> next_callback, 38 MojoResult result) { 39 delete watcher; 40 next_callback.Run(result); 41 } 42 43 // Helper class to manage the callback and running the message loop waiting for 44 // message to be received. Typical usage is something like: 45 // Schedule callback returned from GetCallback(). 46 // RunUntilGotCallback(); 47 // EXPECT_TRUE(got_callback()); 48 // clear_callback(); 49 class CallbackHelper { 50 public: 51 CallbackHelper() 52 : got_callback_(false), 53 run_loop_(NULL), 54 weak_factory_(this) {} 55 ~CallbackHelper() {} 56 57 // See description above |got_callback_|. 58 bool got_callback() const { return got_callback_; } 59 void clear_callback() { got_callback_ = false; } 60 61 // Runs the current MessageLoop until the callback returned from GetCallback() 62 // is notified. 63 void RunUntilGotCallback() { 64 ASSERT_TRUE(run_loop_ == NULL); 65 base::RunLoop run_loop; 66 base::AutoReset<base::RunLoop*> reseter(&run_loop_, &run_loop); 67 run_loop.Run(); 68 } 69 70 base::Callback<void(MojoResult)> GetCallback() { 71 return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr()); 72 } 73 74 void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) { 75 StartWithCallback(watcher, handle, GetCallback()); 76 } 77 78 void StartWithCallback(HandleWatcher* watcher, 79 const MessagePipeHandle& handle, 80 const base::Callback<void(MojoResult)>& callback) { 81 watcher->Start(handle, MOJO_HANDLE_SIGNAL_READABLE, 82 MOJO_DEADLINE_INDEFINITE, callback); 83 } 84 85 private: 86 void OnCallback(MojoResult result) { 87 got_callback_ = true; 88 if (run_loop_) 89 run_loop_->Quit(); 90 } 91 92 // Set to true when the callback is called. 93 bool got_callback_; 94 95 // If non-NULL we're in RunUntilGotCallback(). 96 base::RunLoop* run_loop_; 97 98 base::WeakPtrFactory<CallbackHelper> weak_factory_; 99 100 private: 101 DISALLOW_COPY_AND_ASSIGN(CallbackHelper); 102 }; 103 104 class HandleWatcherTest : public testing::Test { 105 public: 106 HandleWatcherTest() {} 107 virtual ~HandleWatcherTest() { 108 test::SetTickClockForTest(NULL); 109 } 110 111 protected: 112 void InstallTickClock() { 113 test::SetTickClockForTest(&tick_clock_); 114 } 115 116 base::SimpleTestTickClock tick_clock_; 117 118 private: 119 base::ShadowingAtExitManager at_exit_; 120 base::MessageLoop message_loop_; 121 122 DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest); 123 }; 124 125 // Trivial test case with a single handle to watch. 126 TEST_F(HandleWatcherTest, SingleHandler) { 127 MessagePipe test_pipe; 128 ASSERT_TRUE(test_pipe.handle0.is_valid()); 129 CallbackHelper callback_helper; 130 HandleWatcher watcher; 131 callback_helper.Start(&watcher, test_pipe.handle0.get()); 132 RunUntilIdle(); 133 EXPECT_FALSE(callback_helper.got_callback()); 134 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), 135 std::string())); 136 callback_helper.RunUntilGotCallback(); 137 EXPECT_TRUE(callback_helper.got_callback()); 138 } 139 140 // Creates three handles and notfies them in reverse order ensuring each one is 141 // notified appropriately. 142 TEST_F(HandleWatcherTest, ThreeHandles) { 143 MessagePipe test_pipe1; 144 MessagePipe test_pipe2; 145 MessagePipe test_pipe3; 146 CallbackHelper callback_helper1; 147 CallbackHelper callback_helper2; 148 CallbackHelper callback_helper3; 149 ASSERT_TRUE(test_pipe1.handle0.is_valid()); 150 ASSERT_TRUE(test_pipe2.handle0.is_valid()); 151 ASSERT_TRUE(test_pipe3.handle0.is_valid()); 152 153 HandleWatcher watcher1; 154 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 155 RunUntilIdle(); 156 EXPECT_FALSE(callback_helper1.got_callback()); 157 EXPECT_FALSE(callback_helper2.got_callback()); 158 EXPECT_FALSE(callback_helper3.got_callback()); 159 160 HandleWatcher watcher2; 161 callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); 162 RunUntilIdle(); 163 EXPECT_FALSE(callback_helper1.got_callback()); 164 EXPECT_FALSE(callback_helper2.got_callback()); 165 EXPECT_FALSE(callback_helper3.got_callback()); 166 167 HandleWatcher watcher3; 168 callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); 169 RunUntilIdle(); 170 EXPECT_FALSE(callback_helper1.got_callback()); 171 EXPECT_FALSE(callback_helper2.got_callback()); 172 EXPECT_FALSE(callback_helper3.got_callback()); 173 174 // Write to 3 and make sure it's notified. 175 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), 176 std::string())); 177 callback_helper3.RunUntilGotCallback(); 178 EXPECT_FALSE(callback_helper1.got_callback()); 179 EXPECT_FALSE(callback_helper2.got_callback()); 180 EXPECT_TRUE(callback_helper3.got_callback()); 181 callback_helper3.clear_callback(); 182 183 // Write to 1 and 3. Only 1 should be notified since 3 was is no longer 184 // running. 185 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 186 std::string())); 187 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), 188 std::string())); 189 callback_helper1.RunUntilGotCallback(); 190 EXPECT_TRUE(callback_helper1.got_callback()); 191 EXPECT_FALSE(callback_helper2.got_callback()); 192 EXPECT_FALSE(callback_helper3.got_callback()); 193 callback_helper1.clear_callback(); 194 195 // Write to 1 and 2. Only 2 should be notified (since 1 was already notified). 196 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 197 std::string())); 198 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), 199 std::string())); 200 callback_helper2.RunUntilGotCallback(); 201 EXPECT_FALSE(callback_helper1.got_callback()); 202 EXPECT_TRUE(callback_helper2.got_callback()); 203 EXPECT_FALSE(callback_helper3.got_callback()); 204 } 205 206 // Verifies Start() invoked a second time works. 207 TEST_F(HandleWatcherTest, Restart) { 208 MessagePipe test_pipe1; 209 MessagePipe test_pipe2; 210 CallbackHelper callback_helper1; 211 CallbackHelper callback_helper2; 212 ASSERT_TRUE(test_pipe1.handle0.is_valid()); 213 ASSERT_TRUE(test_pipe2.handle0.is_valid()); 214 215 HandleWatcher watcher1; 216 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 217 RunUntilIdle(); 218 EXPECT_FALSE(callback_helper1.got_callback()); 219 EXPECT_FALSE(callback_helper2.got_callback()); 220 221 HandleWatcher watcher2; 222 callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); 223 RunUntilIdle(); 224 EXPECT_FALSE(callback_helper1.got_callback()); 225 EXPECT_FALSE(callback_helper2.got_callback()); 226 227 // Write to 1 and make sure it's notified. 228 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 229 std::string())); 230 callback_helper1.RunUntilGotCallback(); 231 EXPECT_TRUE(callback_helper1.got_callback()); 232 EXPECT_FALSE(callback_helper2.got_callback()); 233 callback_helper1.clear_callback(); 234 EXPECT_TRUE(mojo::test::DiscardMessage(test_pipe1.handle0.get())); 235 236 // Write to 2 and make sure it's notified. 237 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), 238 std::string())); 239 callback_helper2.RunUntilGotCallback(); 240 EXPECT_FALSE(callback_helper1.got_callback()); 241 EXPECT_TRUE(callback_helper2.got_callback()); 242 callback_helper2.clear_callback(); 243 244 // Listen on 1 again. 245 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 246 RunUntilIdle(); 247 EXPECT_FALSE(callback_helper1.got_callback()); 248 EXPECT_FALSE(callback_helper2.got_callback()); 249 250 // Write to 1 and make sure it's notified. 251 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 252 std::string())); 253 callback_helper1.RunUntilGotCallback(); 254 EXPECT_TRUE(callback_helper1.got_callback()); 255 EXPECT_FALSE(callback_helper2.got_callback()); 256 } 257 258 // Verifies deadline is honored. 259 TEST_F(HandleWatcherTest, Deadline) { 260 InstallTickClock(); 261 262 MessagePipe test_pipe1; 263 MessagePipe test_pipe2; 264 MessagePipe test_pipe3; 265 CallbackHelper callback_helper1; 266 CallbackHelper callback_helper2; 267 CallbackHelper callback_helper3; 268 ASSERT_TRUE(test_pipe1.handle0.is_valid()); 269 ASSERT_TRUE(test_pipe2.handle0.is_valid()); 270 ASSERT_TRUE(test_pipe3.handle0.is_valid()); 271 272 // Add a watcher with an infinite timeout. 273 HandleWatcher watcher1; 274 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 275 RunUntilIdle(); 276 EXPECT_FALSE(callback_helper1.got_callback()); 277 EXPECT_FALSE(callback_helper2.got_callback()); 278 EXPECT_FALSE(callback_helper3.got_callback()); 279 280 // Add another watcher wth a timeout of 500 microseconds. 281 HandleWatcher watcher2; 282 watcher2.Start(test_pipe2.handle0.get(), MOJO_HANDLE_SIGNAL_READABLE, 500, 283 callback_helper2.GetCallback()); 284 RunUntilIdle(); 285 EXPECT_FALSE(callback_helper1.got_callback()); 286 EXPECT_FALSE(callback_helper2.got_callback()); 287 EXPECT_FALSE(callback_helper3.got_callback()); 288 289 // Advance the clock passed the deadline. We also have to start another 290 // watcher to wake up the background thread. 291 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(501)); 292 293 HandleWatcher watcher3; 294 callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); 295 296 callback_helper2.RunUntilGotCallback(); 297 EXPECT_FALSE(callback_helper1.got_callback()); 298 EXPECT_TRUE(callback_helper2.got_callback()); 299 EXPECT_FALSE(callback_helper3.got_callback()); 300 } 301 302 TEST_F(HandleWatcherTest, DeleteInCallback) { 303 MessagePipe test_pipe; 304 CallbackHelper callback_helper; 305 306 HandleWatcher* watcher = new HandleWatcher(); 307 callback_helper.StartWithCallback(watcher, test_pipe.handle1.get(), 308 base::Bind(&DeleteWatcherAndForwardResult, 309 watcher, 310 callback_helper.GetCallback())); 311 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle0.get(), 312 std::string())); 313 callback_helper.RunUntilGotCallback(); 314 EXPECT_TRUE(callback_helper.got_callback()); 315 } 316 317 TEST(HandleWatcherCleanEnvironmentTest, AbortedOnMessageLoopDestruction) { 318 bool was_signaled = false; 319 MojoResult result = MOJO_RESULT_OK; 320 321 base::ShadowingAtExitManager at_exit; 322 MessagePipe pipe; 323 HandleWatcher watcher; 324 { 325 base::MessageLoop loop; 326 327 watcher.Start(pipe.handle0.get(), 328 MOJO_HANDLE_SIGNAL_READABLE, 329 MOJO_DEADLINE_INDEFINITE, 330 base::Bind(&ObserveCallback, &was_signaled, &result)); 331 332 // Now, let the MessageLoop get torn down. We expect our callback to run. 333 } 334 335 EXPECT_TRUE(was_signaled); 336 EXPECT_EQ(MOJO_RESULT_ABORTED, result); 337 } 338 339 } // namespace test 340 } // namespace common 341 } // namespace mojo 342