1 // Copyright 2015 The Chromium OS 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 <brillo/message_loops/message_loop.h> 6 7 // These are the common tests for all the brillo::MessageLoop implementations 8 // that should conform to this interface's contracts. For extra 9 // implementation-specific tests see the particular implementation unittests in 10 // the *_unittest.cc files. 11 12 #include <memory> 13 #include <vector> 14 15 #include <base/bind.h> 16 #include <base/bind_helpers.h> 17 #include <base/location.h> 18 #include <base/posix/eintr_wrapper.h> 19 #include <gtest/gtest.h> 20 21 #include <brillo/bind_lambda.h> 22 #include <brillo/unittest_utils.h> 23 #include <brillo/message_loops/base_message_loop.h> 24 #include <brillo/message_loops/message_loop_utils.h> 25 26 using base::Bind; 27 using base::TimeDelta; 28 29 namespace { 30 31 // Convenience functions for passing to base::Bind. 32 void SetToTrue(bool* b) { 33 *b = true; 34 } 35 36 bool ReturnBool(bool *b) { 37 return *b; 38 } 39 40 void Increment(int* i) { 41 (*i)++; 42 } 43 44 } // namespace 45 46 namespace brillo { 47 48 using TaskId = MessageLoop::TaskId; 49 50 template <typename T> 51 class MessageLoopTest : public ::testing::Test { 52 protected: 53 void SetUp() override { 54 MessageLoopSetUp(); 55 EXPECT_TRUE(this->loop_.get()); 56 } 57 58 std::unique_ptr<base::MessageLoopForIO> base_loop_; 59 60 std::unique_ptr<MessageLoop> loop_; 61 62 private: 63 // These MessageLoopSetUp() methods are used to setup each MessageLoop 64 // according to its constructor requirements. 65 void MessageLoopSetUp(); 66 }; 67 68 template <> 69 void MessageLoopTest<BaseMessageLoop>::MessageLoopSetUp() { 70 base_loop_.reset(new base::MessageLoopForIO()); 71 loop_.reset(new BaseMessageLoop(base::MessageLoopForIO::current())); 72 } 73 74 // This setups gtest to run each one of the following TYPED_TEST test cases on 75 // on each implementation. 76 typedef ::testing::Types<BaseMessageLoop> MessageLoopTypes; 77 TYPED_TEST_CASE(MessageLoopTest, MessageLoopTypes); 78 79 80 TYPED_TEST(MessageLoopTest, CancelTaskInvalidValuesTest) { 81 EXPECT_FALSE(this->loop_->CancelTask(MessageLoop::kTaskIdNull)); 82 EXPECT_FALSE(this->loop_->CancelTask(1234)); 83 } 84 85 TYPED_TEST(MessageLoopTest, PostTaskTest) { 86 bool called = false; 87 TaskId task_id = this->loop_->PostTask(FROM_HERE, Bind(&SetToTrue, &called)); 88 EXPECT_NE(MessageLoop::kTaskIdNull, task_id); 89 MessageLoopRunMaxIterations(this->loop_.get(), 100); 90 EXPECT_TRUE(called); 91 } 92 93 // Tests that we can cancel tasks right after we schedule them. 94 TYPED_TEST(MessageLoopTest, PostTaskCancelledTest) { 95 bool called = false; 96 TaskId task_id = this->loop_->PostTask(FROM_HERE, Bind(&SetToTrue, &called)); 97 EXPECT_TRUE(this->loop_->CancelTask(task_id)); 98 MessageLoopRunMaxIterations(this->loop_.get(), 100); 99 EXPECT_FALSE(called); 100 // Can't remove a task you already removed. 101 EXPECT_FALSE(this->loop_->CancelTask(task_id)); 102 } 103 104 TYPED_TEST(MessageLoopTest, PostDelayedTaskRunsEventuallyTest) { 105 bool called = false; 106 TaskId task_id = this->loop_->PostDelayedTask( 107 FROM_HERE, Bind(&SetToTrue, &called), TimeDelta::FromMilliseconds(50)); 108 EXPECT_NE(MessageLoop::kTaskIdNull, task_id); 109 MessageLoopRunUntil(this->loop_.get(), 110 TimeDelta::FromSeconds(10), 111 Bind(&ReturnBool, &called)); 112 // Check that the main loop finished before the 10 seconds timeout, so it 113 // finished due to the callback being called and not due to the timeout. 114 EXPECT_TRUE(called); 115 } 116 117 // Test that you can call the overloaded version of PostDelayedTask from 118 // MessageLoop. This is important because only one of the two methods is 119 // virtual, so you need to unhide the other when overriding the virtual one. 120 TYPED_TEST(MessageLoopTest, PostDelayedTaskWithoutLocation) { 121 this->loop_->PostDelayedTask(base::DoNothing(), TimeDelta()); 122 EXPECT_EQ(1, MessageLoopRunMaxIterations(this->loop_.get(), 100)); 123 } 124 125 TYPED_TEST(MessageLoopTest, WatchForInvalidFD) { 126 bool called = false; 127 EXPECT_EQ(MessageLoop::kTaskIdNull, this->loop_->WatchFileDescriptor( 128 FROM_HERE, -1, MessageLoop::kWatchRead, true, 129 Bind(&SetToTrue, &called))); 130 EXPECT_EQ(MessageLoop::kTaskIdNull, this->loop_->WatchFileDescriptor( 131 FROM_HERE, -1, MessageLoop::kWatchWrite, true, 132 Bind(&SetToTrue, &called))); 133 EXPECT_EQ(0, MessageLoopRunMaxIterations(this->loop_.get(), 100)); 134 EXPECT_FALSE(called); 135 } 136 137 TYPED_TEST(MessageLoopTest, CancelWatchedFileDescriptor) { 138 ScopedPipe pipe; 139 bool called = false; 140 TaskId task_id = this->loop_->WatchFileDescriptor( 141 FROM_HERE, pipe.reader, MessageLoop::kWatchRead, true, 142 Bind(&SetToTrue, &called)); 143 EXPECT_NE(MessageLoop::kTaskIdNull, task_id); 144 // The reader end is blocked because we didn't write anything to the writer 145 // end. 146 EXPECT_EQ(0, MessageLoopRunMaxIterations(this->loop_.get(), 100)); 147 EXPECT_FALSE(called); 148 EXPECT_TRUE(this->loop_->CancelTask(task_id)); 149 } 150 151 // When you watch a file descriptor for reading, the guaranties are that a 152 // blocking call to read() on that file descriptor will not block. This should 153 // include the case when the other end of a pipe is closed or the file is empty. 154 TYPED_TEST(MessageLoopTest, WatchFileDescriptorTriggersWhenPipeClosed) { 155 ScopedPipe pipe; 156 bool called = false; 157 EXPECT_EQ(0, HANDLE_EINTR(close(pipe.writer))); 158 pipe.writer = -1; 159 TaskId task_id = this->loop_->WatchFileDescriptor( 160 FROM_HERE, pipe.reader, MessageLoop::kWatchRead, true, 161 Bind(&SetToTrue, &called)); 162 EXPECT_NE(MessageLoop::kTaskIdNull, task_id); 163 // The reader end is not blocked because we closed the writer end so a read on 164 // the reader end would return 0 bytes read. 165 EXPECT_NE(0, MessageLoopRunMaxIterations(this->loop_.get(), 10)); 166 EXPECT_TRUE(called); 167 EXPECT_TRUE(this->loop_->CancelTask(task_id)); 168 } 169 170 // When a WatchFileDescriptor task is scheduled with |persistent| = true, we 171 // should keep getting a call whenever the file descriptor is ready. 172 TYPED_TEST(MessageLoopTest, WatchFileDescriptorPersistently) { 173 ScopedPipe pipe; 174 EXPECT_EQ(1, HANDLE_EINTR(write(pipe.writer, "a", 1))); 175 176 int called = 0; 177 TaskId task_id = this->loop_->WatchFileDescriptor( 178 FROM_HERE, pipe.reader, MessageLoop::kWatchRead, true, 179 Bind(&Increment, &called)); 180 EXPECT_NE(MessageLoop::kTaskIdNull, task_id); 181 // We let the main loop run for 20 iterations to give it enough iterations to 182 // verify that our callback was called more than one. We only check that our 183 // callback is called more than once. 184 EXPECT_EQ(20, MessageLoopRunMaxIterations(this->loop_.get(), 20)); 185 EXPECT_LT(1, called); 186 EXPECT_TRUE(this->loop_->CancelTask(task_id)); 187 } 188 189 TYPED_TEST(MessageLoopTest, WatchFileDescriptorNonPersistent) { 190 ScopedPipe pipe; 191 EXPECT_EQ(1, HANDLE_EINTR(write(pipe.writer, "a", 1))); 192 193 int called = 0; 194 TaskId task_id = this->loop_->WatchFileDescriptor( 195 FROM_HERE, pipe.reader, MessageLoop::kWatchRead, false, 196 Bind(&Increment, &called)); 197 EXPECT_NE(MessageLoop::kTaskIdNull, task_id); 198 // We let the main loop run for 20 iterations but we just expect it to run 199 // at least once. The callback should be called exactly once since we 200 // scheduled it non-persistently. After it ran, we shouldn't be able to cancel 201 // this task. 202 EXPECT_LT(0, MessageLoopRunMaxIterations(this->loop_.get(), 20)); 203 EXPECT_EQ(1, called); 204 EXPECT_FALSE(this->loop_->CancelTask(task_id)); 205 } 206 207 TYPED_TEST(MessageLoopTest, WatchFileDescriptorForReadAndWriteSimultaneously) { 208 ScopedSocketPair socks; 209 EXPECT_EQ(1, HANDLE_EINTR(write(socks.right, "a", 1))); 210 // socks.left should be able to read this "a" and should also be able to write 211 // without blocking since the kernel has some buffering for it. 212 213 TaskId read_task_id = this->loop_->WatchFileDescriptor( 214 FROM_HERE, socks.left, MessageLoop::kWatchRead, true, 215 Bind([] (MessageLoop* loop, TaskId* read_task_id) { 216 EXPECT_TRUE(loop->CancelTask(*read_task_id)) 217 << "task_id" << *read_task_id; 218 }, this->loop_.get(), &read_task_id)); 219 EXPECT_NE(MessageLoop::kTaskIdNull, read_task_id); 220 221 TaskId write_task_id = this->loop_->WatchFileDescriptor( 222 FROM_HERE, socks.left, MessageLoop::kWatchWrite, true, 223 Bind([] (MessageLoop* loop, TaskId* write_task_id) { 224 EXPECT_TRUE(loop->CancelTask(*write_task_id)); 225 }, this->loop_.get(), &write_task_id)); 226 EXPECT_NE(MessageLoop::kTaskIdNull, write_task_id); 227 228 EXPECT_LT(0, MessageLoopRunMaxIterations(this->loop_.get(), 20)); 229 230 EXPECT_FALSE(this->loop_->CancelTask(read_task_id)); 231 EXPECT_FALSE(this->loop_->CancelTask(write_task_id)); 232 } 233 234 // Test that we can cancel the task we are running, and should just fail. 235 TYPED_TEST(MessageLoopTest, DeleteTaskFromSelf) { 236 bool cancel_result = true; // We would expect this to be false. 237 TaskId task_id; 238 task_id = this->loop_->PostTask( 239 FROM_HERE, 240 Bind([](bool* cancel_result, MessageLoop* loop, TaskId* task_id) { 241 *cancel_result = loop->CancelTask(*task_id); 242 }, &cancel_result, this->loop_.get(), &task_id)); 243 EXPECT_EQ(1, MessageLoopRunMaxIterations(this->loop_.get(), 100)); 244 EXPECT_FALSE(cancel_result); 245 } 246 247 // Test that we can cancel a non-persistent file descriptor watching callback, 248 // which should fail. 249 TYPED_TEST(MessageLoopTest, DeleteNonPersistenIOTaskFromSelf) { 250 ScopedPipe pipe; 251 TaskId task_id = this->loop_->WatchFileDescriptor( 252 FROM_HERE, pipe.writer, MessageLoop::kWatchWrite, false /* persistent */, 253 Bind([](MessageLoop* loop, TaskId* task_id) { 254 EXPECT_FALSE(loop->CancelTask(*task_id)); 255 *task_id = MessageLoop::kTaskIdNull; 256 }, this->loop_.get(), &task_id)); 257 EXPECT_NE(MessageLoop::kTaskIdNull, task_id); 258 EXPECT_EQ(1, MessageLoopRunMaxIterations(this->loop_.get(), 100)); 259 EXPECT_EQ(MessageLoop::kTaskIdNull, task_id); 260 } 261 262 // Test that we can cancel a persistent file descriptor watching callback from 263 // the same callback. 264 TYPED_TEST(MessageLoopTest, DeletePersistenIOTaskFromSelf) { 265 ScopedPipe pipe; 266 TaskId task_id = this->loop_->WatchFileDescriptor( 267 FROM_HERE, pipe.writer, MessageLoop::kWatchWrite, true /* persistent */, 268 Bind([](MessageLoop* loop, TaskId* task_id) { 269 EXPECT_TRUE(loop->CancelTask(*task_id)); 270 *task_id = MessageLoop::kTaskIdNull; 271 }, this->loop_.get(), &task_id)); 272 EXPECT_NE(MessageLoop::kTaskIdNull, task_id); 273 EXPECT_EQ(1, MessageLoopRunMaxIterations(this->loop_.get(), 100)); 274 EXPECT_EQ(MessageLoop::kTaskIdNull, task_id); 275 } 276 277 // Test that we can cancel several persistent file descriptor watching callbacks 278 // from a scheduled callback. In the BaseMessageLoop implementation, this code 279 // will cause us to cancel an IOTask that has a pending delayed task, but 280 // otherwise is a valid test case on all implementations. 281 TYPED_TEST(MessageLoopTest, DeleteAllPersistenIOTaskFromSelf) { 282 const int kNumTasks = 5; 283 ScopedPipe pipes[kNumTasks]; 284 TaskId task_ids[kNumTasks]; 285 286 for (int i = 0; i < kNumTasks; ++i) { 287 task_ids[i] = this->loop_->WatchFileDescriptor( 288 FROM_HERE, pipes[i].writer, MessageLoop::kWatchWrite, 289 true /* persistent */, 290 Bind([] (MessageLoop* loop, TaskId* task_ids) { 291 for (int j = 0; j < kNumTasks; ++j) { 292 // Once we cancel all the tasks, none should run, so this code runs 293 // only once from one callback. 294 EXPECT_TRUE(loop->CancelTask(task_ids[j])); 295 task_ids[j] = MessageLoop::kTaskIdNull; 296 } 297 }, this->loop_.get(), task_ids)); 298 } 299 MessageLoopRunMaxIterations(this->loop_.get(), 100); 300 for (int i = 0; i < kNumTasks; ++i) { 301 EXPECT_EQ(MessageLoop::kTaskIdNull, task_ids[i]); 302 } 303 } 304 305 // Test that if there are several tasks watching for file descriptors to be 306 // available or simply waiting in the message loop are fairly scheduled to run. 307 // In other words, this test ensures that having a file descriptor always 308 // available doesn't prevent other file descriptors watching tasks or delayed 309 // tasks to be dispatched, causing starvation. 310 TYPED_TEST(MessageLoopTest, AllTasksAreEqual) { 311 int total_calls = 0; 312 313 // First, schedule a repeating timeout callback to run from the main loop. 314 int timeout_called = 0; 315 base::Closure timeout_callback; 316 MessageLoop::TaskId timeout_task; 317 timeout_callback = base::Bind( 318 [](MessageLoop* loop, int* timeout_called, int* total_calls, 319 base::Closure* timeout_callback, MessageLoop::TaskId* timeout_task) { 320 (*timeout_called)++; 321 (*total_calls)++; 322 *timeout_task = loop->PostTask(FROM_HERE, *timeout_callback); 323 if (*total_calls > 100) 324 loop->BreakLoop(); 325 }, 326 this->loop_.get(), &timeout_called, &total_calls, &timeout_callback, 327 &timeout_task); 328 timeout_task = this->loop_->PostTask(FROM_HERE, timeout_callback); 329 330 // Second, schedule several file descriptor watchers. 331 const int kNumTasks = 3; 332 ScopedPipe pipes[kNumTasks]; 333 MessageLoop::TaskId tasks[kNumTasks]; 334 335 int reads[kNumTasks] = {}; 336 base::Callback<void(int)> fd_callback = base::Bind( 337 [](MessageLoop* loop, ScopedPipe* pipes, int* reads, 338 int* total_calls, int i) { 339 reads[i]++; 340 (*total_calls)++; 341 char c; 342 EXPECT_EQ(1, HANDLE_EINTR(read(pipes[i].reader, &c, 1))); 343 if (*total_calls > 100) 344 loop->BreakLoop(); 345 }, this->loop_.get(), pipes, reads, &total_calls); 346 347 for (int i = 0; i < kNumTasks; ++i) { 348 tasks[i] = this->loop_->WatchFileDescriptor( 349 FROM_HERE, pipes[i].reader, MessageLoop::kWatchRead, 350 true /* persistent */, 351 Bind(fd_callback, i)); 352 // Make enough bytes available on each file descriptor. This should not 353 // block because we set the size of the file descriptor buffer when 354 // creating it. 355 std::vector<char> blob(1000, 'a'); 356 EXPECT_EQ(blob.size(), 357 HANDLE_EINTR(write(pipes[i].writer, blob.data(), blob.size()))); 358 } 359 this->loop_->Run(); 360 EXPECT_GT(total_calls, 100); 361 // We run the loop up 100 times and expect each callback to run at least 10 362 // times. A good scheduler should balance these callbacks. 363 EXPECT_GE(timeout_called, 10); 364 EXPECT_TRUE(this->loop_->CancelTask(timeout_task)); 365 for (int i = 0; i < kNumTasks; ++i) { 366 EXPECT_GE(reads[i], 10) << "Reading from pipes[" << i << "], fd " 367 << pipes[i].reader; 368 EXPECT_TRUE(this->loop_->CancelTask(tasks[i])); 369 } 370 } 371 372 } // namespace brillo 373