handle_watcher_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
107b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// Copyright 2013 The Chromium Authors. All rights reserved. 207b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// Use of this source code is governed by a BSD-style license that can be 39be1d37a9a6561f135412db66806def9f82a29c1steveblock@chromium.org// found in the LICENSE file. 407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org 507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "mojo/common/handle_watcher.h" 607b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org 707b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include <string> 87a9d1ab1b214d7342b5a6d3ae4837fd572a8f4d0evan@chromium.org 907b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "base/auto_reset.h" 1007b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "base/bind.h" 1107b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "base/run_loop.h" 1207b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "base/test/simple_test_tick_clock.h" 1307b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "mojo/public/system/core_cpp.h" 1407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "mojo/public/tests/test_utils.h" 1507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org#include "testing/gtest/include/gtest/gtest.h" 16dc9d50a9c015fa86d8ffae123d63173cf5bd7b73torne@chromium.org 17dc9d50a9c015fa86d8ffae123d63173cf5bd7b73torne@chromium.orgnamespace mojo { 1807b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.orgnamespace common { 1907b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.orgnamespace test { 2007b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org 218051f4242ca0291165aef138ab4b621eb3128d92thomasvl@chromium.orgvoid RunUntilIdle() { 2207b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org base::RunLoop run_loop; 2307b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org run_loop.RunUntilIdle(); 247a9d1ab1b214d7342b5a6d3ae4837fd572a8f4d0evan@chromium.org} 2507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org 2607b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.orgvoid DeleteWatcherAndForwardResult( 2707b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org HandleWatcher* watcher, 2807b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org base::Callback<void(MojoResult)> next_callback, 2907b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org MojoResult result) { 3007b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org delete watcher; 31a7fd578d98e5fff82dfd51d8a8e41f8392ff38b7bradnelson@google.com next_callback.Run(result); 3207b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org} 337a9d1ab1b214d7342b5a6d3ae4837fd572a8f4d0evan@chromium.org 3407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// Helper class to manage the callback and running the message loop waiting for 3507b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// message to be received. Typical usage is something like: 3607b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// Schedule callback returned from GetCallback(). 3707b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// RunUntilGotCallback(); 388051f4242ca0291165aef138ab4b621eb3128d92thomasvl@chromium.org// EXPECT_TRUE(got_callback()); 3907b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org// clear_callback(); 4007b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.orgclass CallbackHelper { 4107b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org public: 42a7fd578d98e5fff82dfd51d8a8e41f8392ff38b7bradnelson@google.com CallbackHelper() 4307b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org : got_callback_(false), 4407b131e8ffa26908c78fa6fdc54afaae01367febmmoss@chromium.org run_loop_(NULL), 45 weak_factory_(this) {} 46 ~CallbackHelper() {} 47 48 // See description above |got_callback_|. 49 bool got_callback() const { return got_callback_; } 50 void clear_callback() { got_callback_ = false; } 51 52 // Runs the current MessageLoop until the callback returned from GetCallback() 53 // is notified. 54 void RunUntilGotCallback() { 55 ASSERT_TRUE(run_loop_ == NULL); 56 base::RunLoop run_loop; 57 base::AutoReset<base::RunLoop*> reseter(&run_loop_, &run_loop); 58 run_loop.Run(); 59 } 60 61 base::Callback<void(MojoResult)> GetCallback() { 62 return base::Bind(&CallbackHelper::OnCallback, weak_factory_.GetWeakPtr()); 63 } 64 65 void Start(HandleWatcher* watcher, const MessagePipeHandle& handle) { 66 StartWithCallback(watcher, handle, GetCallback()); 67 } 68 69 void StartWithCallback(HandleWatcher* watcher, 70 const MessagePipeHandle& handle, 71 const base::Callback<void(MojoResult)>& callback) { 72 watcher->Start(handle, MOJO_WAIT_FLAG_READABLE, MOJO_DEADLINE_INDEFINITE, 73 callback); 74 } 75 76 private: 77 void OnCallback(MojoResult result) { 78 got_callback_ = true; 79 if (run_loop_) 80 run_loop_->Quit(); 81 } 82 83 // Set to true when the callback is called. 84 bool got_callback_; 85 86 // If non-NULL we're in RunUntilGotCallback(). 87 base::RunLoop* run_loop_; 88 89 base::WeakPtrFactory<CallbackHelper> weak_factory_; 90 91 private: 92 DISALLOW_COPY_AND_ASSIGN(CallbackHelper); 93}; 94 95class HandleWatcherTest : public testing::Test { 96 public: 97 HandleWatcherTest() {} 98 virtual ~HandleWatcherTest() { 99 HandleWatcher::tick_clock_ = NULL; 100 } 101 102 protected: 103 void InstallTickClock() { 104 HandleWatcher::tick_clock_ = &tick_clock_; 105 } 106 107 base::SimpleTestTickClock tick_clock_; 108 109 private: 110 base::MessageLoop message_loop_; 111 112 DISALLOW_COPY_AND_ASSIGN(HandleWatcherTest); 113}; 114 115// Trivial test case with a single handle to watch. 116TEST_F(HandleWatcherTest, SingleHandler) { 117 MessagePipe test_pipe; 118 ASSERT_TRUE(test_pipe.handle0.is_valid()); 119 CallbackHelper callback_helper; 120 HandleWatcher watcher; 121 callback_helper.Start(&watcher, test_pipe.handle0.get()); 122 RunUntilIdle(); 123 EXPECT_FALSE(callback_helper.got_callback()); 124 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle1.get(), 125 std::string())); 126 callback_helper.RunUntilGotCallback(); 127 EXPECT_TRUE(callback_helper.got_callback()); 128} 129 130// Creates three handles and notfies them in reverse order ensuring each one is 131// notified appropriately. 132TEST_F(HandleWatcherTest, ThreeHandles) { 133 MessagePipe test_pipe1; 134 MessagePipe test_pipe2; 135 MessagePipe test_pipe3; 136 CallbackHelper callback_helper1; 137 CallbackHelper callback_helper2; 138 CallbackHelper callback_helper3; 139 ASSERT_TRUE(test_pipe1.handle0.is_valid()); 140 ASSERT_TRUE(test_pipe2.handle0.is_valid()); 141 ASSERT_TRUE(test_pipe3.handle0.is_valid()); 142 143 HandleWatcher watcher1; 144 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 145 RunUntilIdle(); 146 EXPECT_FALSE(callback_helper1.got_callback()); 147 EXPECT_FALSE(callback_helper2.got_callback()); 148 EXPECT_FALSE(callback_helper3.got_callback()); 149 150 HandleWatcher watcher2; 151 callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); 152 RunUntilIdle(); 153 EXPECT_FALSE(callback_helper1.got_callback()); 154 EXPECT_FALSE(callback_helper2.got_callback()); 155 EXPECT_FALSE(callback_helper3.got_callback()); 156 157 HandleWatcher watcher3; 158 callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); 159 RunUntilIdle(); 160 EXPECT_FALSE(callback_helper1.got_callback()); 161 EXPECT_FALSE(callback_helper2.got_callback()); 162 EXPECT_FALSE(callback_helper3.got_callback()); 163 164 // Write to 3 and make sure it's notified. 165 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), 166 std::string())); 167 callback_helper3.RunUntilGotCallback(); 168 EXPECT_FALSE(callback_helper1.got_callback()); 169 EXPECT_FALSE(callback_helper2.got_callback()); 170 EXPECT_TRUE(callback_helper3.got_callback()); 171 callback_helper3.clear_callback(); 172 173 // Write to 1 and 3. Only 1 should be notified since 3 was is no longer 174 // running. 175 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 176 std::string())); 177 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe3.handle1.get(), 178 std::string())); 179 callback_helper1.RunUntilGotCallback(); 180 EXPECT_TRUE(callback_helper1.got_callback()); 181 EXPECT_FALSE(callback_helper2.got_callback()); 182 EXPECT_FALSE(callback_helper3.got_callback()); 183 callback_helper1.clear_callback(); 184 185 // Write to 1 and 2. Only 2 should be notified (since 1 was already notified). 186 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 187 std::string())); 188 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), 189 std::string())); 190 callback_helper2.RunUntilGotCallback(); 191 EXPECT_FALSE(callback_helper1.got_callback()); 192 EXPECT_TRUE(callback_helper2.got_callback()); 193 EXPECT_FALSE(callback_helper3.got_callback()); 194} 195 196// Verifies Start() invoked a second time works. 197TEST_F(HandleWatcherTest, Restart) { 198 MessagePipe test_pipe1; 199 MessagePipe test_pipe2; 200 CallbackHelper callback_helper1; 201 CallbackHelper callback_helper2; 202 ASSERT_TRUE(test_pipe1.handle0.is_valid()); 203 ASSERT_TRUE(test_pipe2.handle0.is_valid()); 204 205 HandleWatcher watcher1; 206 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 207 RunUntilIdle(); 208 EXPECT_FALSE(callback_helper1.got_callback()); 209 EXPECT_FALSE(callback_helper2.got_callback()); 210 211 HandleWatcher watcher2; 212 callback_helper2.Start(&watcher2, test_pipe2.handle0.get()); 213 RunUntilIdle(); 214 EXPECT_FALSE(callback_helper1.got_callback()); 215 EXPECT_FALSE(callback_helper2.got_callback()); 216 217 // Write to 1 and make sure it's notified. 218 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 219 std::string())); 220 callback_helper1.RunUntilGotCallback(); 221 EXPECT_TRUE(callback_helper1.got_callback()); 222 EXPECT_FALSE(callback_helper2.got_callback()); 223 callback_helper1.clear_callback(); 224 EXPECT_TRUE(mojo::test::DiscardMessage(test_pipe1.handle0.get())); 225 226 // Write to 2 and make sure it's notified. 227 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe2.handle1.get(), 228 std::string())); 229 callback_helper2.RunUntilGotCallback(); 230 EXPECT_FALSE(callback_helper1.got_callback()); 231 EXPECT_TRUE(callback_helper2.got_callback()); 232 callback_helper2.clear_callback(); 233 234 // Listen on 1 again. 235 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 236 RunUntilIdle(); 237 EXPECT_FALSE(callback_helper1.got_callback()); 238 EXPECT_FALSE(callback_helper2.got_callback()); 239 240 // Write to 1 and make sure it's notified. 241 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe1.handle1.get(), 242 std::string())); 243 callback_helper1.RunUntilGotCallback(); 244 EXPECT_TRUE(callback_helper1.got_callback()); 245 EXPECT_FALSE(callback_helper2.got_callback()); 246} 247 248// Verifies deadline is honored. 249TEST_F(HandleWatcherTest, Deadline) { 250 InstallTickClock(); 251 252 MessagePipe test_pipe1; 253 MessagePipe test_pipe2; 254 MessagePipe test_pipe3; 255 CallbackHelper callback_helper1; 256 CallbackHelper callback_helper2; 257 CallbackHelper callback_helper3; 258 ASSERT_TRUE(test_pipe1.handle0.is_valid()); 259 ASSERT_TRUE(test_pipe2.handle0.is_valid()); 260 ASSERT_TRUE(test_pipe3.handle0.is_valid()); 261 262 // Add a watcher with an infinite timeout. 263 HandleWatcher watcher1; 264 callback_helper1.Start(&watcher1, test_pipe1.handle0.get()); 265 RunUntilIdle(); 266 EXPECT_FALSE(callback_helper1.got_callback()); 267 EXPECT_FALSE(callback_helper2.got_callback()); 268 EXPECT_FALSE(callback_helper3.got_callback()); 269 270 // Add another watcher wth a timeout of 500 microseconds. 271 HandleWatcher watcher2; 272 watcher2.Start(test_pipe2.handle0.get(), MOJO_WAIT_FLAG_READABLE, 500, 273 callback_helper2.GetCallback()); 274 RunUntilIdle(); 275 EXPECT_FALSE(callback_helper1.got_callback()); 276 EXPECT_FALSE(callback_helper2.got_callback()); 277 EXPECT_FALSE(callback_helper3.got_callback()); 278 279 // Advance the clock passed the deadline. We also have to start another 280 // watcher to wake up the background thread. 281 tick_clock_.Advance(base::TimeDelta::FromMicroseconds(501)); 282 283 HandleWatcher watcher3; 284 callback_helper3.Start(&watcher3, test_pipe3.handle0.get()); 285 286 callback_helper2.RunUntilGotCallback(); 287 EXPECT_FALSE(callback_helper1.got_callback()); 288 EXPECT_TRUE(callback_helper2.got_callback()); 289 EXPECT_FALSE(callback_helper3.got_callback()); 290} 291 292TEST_F(HandleWatcherTest, DeleteInCallback) { 293 MessagePipe test_pipe; 294 CallbackHelper callback_helper; 295 296 HandleWatcher* watcher = new HandleWatcher(); 297 callback_helper.StartWithCallback(watcher, test_pipe.handle1.get(), 298 base::Bind(&DeleteWatcherAndForwardResult, 299 watcher, 300 callback_helper.GetCallback())); 301 EXPECT_TRUE(mojo::test::WriteTextMessage(test_pipe.handle0.get(), 302 std::string())); 303 callback_helper.RunUntilGotCallback(); 304 EXPECT_TRUE(callback_helper.got_callback()); 305} 306 307} // namespace test 308} // namespace common 309} // namespace mojo 310