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