1 // 2 // Copyright 2010 The Android Open Source Project 3 // 4 5 #include <utils/Looper.h> 6 #include <utils/Timers.h> 7 #include <utils/StopWatch.h> 8 #include <gtest/gtest.h> 9 #include <unistd.h> 10 #include <time.h> 11 12 #include "TestHelpers.h" 13 14 // # of milliseconds to fudge stopwatch measurements 15 #define TIMING_TOLERANCE_MS 25 16 17 namespace android { 18 19 class DelayedWake : public DelayedTask { 20 sp<Looper> mLooper; 21 22 public: 23 DelayedWake(int delayMillis, const sp<Looper> looper) : 24 DelayedTask(delayMillis), mLooper(looper) { 25 } 26 27 protected: 28 virtual void doTask() { 29 mLooper->wake(); 30 } 31 }; 32 33 class DelayedWriteSignal : public DelayedTask { 34 Pipe* mPipe; 35 36 public: 37 DelayedWriteSignal(int delayMillis, Pipe* pipe) : 38 DelayedTask(delayMillis), mPipe(pipe) { 39 } 40 41 protected: 42 virtual void doTask() { 43 mPipe->writeSignal(); 44 } 45 }; 46 47 class CallbackHandler { 48 public: 49 void setCallback(const sp<Looper>& looper, int fd, int events) { 50 looper->addFd(fd, 0, events, staticHandler, this); 51 } 52 53 protected: 54 virtual ~CallbackHandler() { } 55 56 virtual int handler(int fd, int events) = 0; 57 58 private: 59 static int staticHandler(int fd, int events, void* data) { 60 return static_cast<CallbackHandler*>(data)->handler(fd, events); 61 } 62 }; 63 64 class StubCallbackHandler : public CallbackHandler { 65 public: 66 int nextResult; 67 int callbackCount; 68 69 int fd; 70 int events; 71 72 StubCallbackHandler(int nextResult) : nextResult(nextResult), 73 callbackCount(0), fd(-1), events(-1) { 74 } 75 76 protected: 77 virtual int handler(int fd, int events) { 78 callbackCount += 1; 79 this->fd = fd; 80 this->events = events; 81 return nextResult; 82 } 83 }; 84 85 class LooperTest : public testing::Test { 86 protected: 87 sp<Looper> mLooper; 88 89 virtual void SetUp() { 90 mLooper = new Looper(true); 91 } 92 93 virtual void TearDown() { 94 mLooper.clear(); 95 } 96 }; 97 98 99 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndNotAwoken_WaitsForTimeout) { 100 StopWatch stopWatch("pollOnce"); 101 int result = mLooper->pollOnce(100); 102 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 103 104 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS) 105 << "elapsed time should approx. equal timeout"; 106 EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) 107 << "pollOnce result should be ALOOPER_POLL_TIMEOUT"; 108 } 109 110 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndAwokenBeforeWaiting_ImmediatelyReturns) { 111 mLooper->wake(); 112 113 StopWatch stopWatch("pollOnce"); 114 int result = mLooper->pollOnce(1000); 115 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 116 117 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) 118 << "elapsed time should approx. zero because wake() was called before waiting"; 119 EXPECT_EQ(ALOOPER_POLL_WAKE, result) 120 << "pollOnce result should be ALOOPER_POLL_CALLBACK because loop was awoken"; 121 } 122 123 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndAwokenWhileWaiting_PromptlyReturns) { 124 sp<DelayedWake> delayedWake = new DelayedWake(100, mLooper); 125 delayedWake->run(); 126 127 StopWatch stopWatch("pollOnce"); 128 int result = mLooper->pollOnce(1000); 129 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 130 131 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS) 132 << "elapsed time should approx. equal wake delay"; 133 EXPECT_EQ(ALOOPER_POLL_WAKE, result) 134 << "pollOnce result should be ALOOPER_POLL_CALLBACK because loop was awoken"; 135 } 136 137 TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndNoRegisteredFDs_ImmediatelyReturns) { 138 StopWatch stopWatch("pollOnce"); 139 int result = mLooper->pollOnce(0); 140 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 141 142 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) 143 << "elapsed time should be approx. zero"; 144 EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) 145 << "pollOnce result should be ALOOPER_POLL_TIMEOUT"; 146 } 147 148 TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndNoSignalledFDs_ImmediatelyReturns) { 149 Pipe pipe; 150 StubCallbackHandler handler(true); 151 152 handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); 153 154 StopWatch stopWatch("pollOnce"); 155 int result = mLooper->pollOnce(0); 156 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 157 158 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) 159 << "elapsed time should be approx. zero"; 160 EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) 161 << "pollOnce result should be ALOOPER_POLL_TIMEOUT"; 162 EXPECT_EQ(0, handler.callbackCount) 163 << "callback should not have been invoked because FD was not signalled"; 164 } 165 166 TEST_F(LooperTest, PollOnce_WhenZeroTimeoutAndSignalledFD_ImmediatelyInvokesCallbackAndReturns) { 167 Pipe pipe; 168 StubCallbackHandler handler(true); 169 170 ASSERT_EQ(OK, pipe.writeSignal()); 171 handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); 172 173 StopWatch stopWatch("pollOnce"); 174 int result = mLooper->pollOnce(0); 175 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 176 177 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) 178 << "elapsed time should be approx. zero"; 179 EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) 180 << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled"; 181 EXPECT_EQ(1, handler.callbackCount) 182 << "callback should be invoked exactly once"; 183 EXPECT_EQ(pipe.receiveFd, handler.fd) 184 << "callback should have received pipe fd as parameter"; 185 EXPECT_EQ(ALOOPER_EVENT_INPUT, handler.events) 186 << "callback should have received ALOOPER_EVENT_INPUT as events"; 187 } 188 189 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndNoSignalledFDs_WaitsForTimeoutAndReturns) { 190 Pipe pipe; 191 StubCallbackHandler handler(true); 192 193 handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); 194 195 StopWatch stopWatch("pollOnce"); 196 int result = mLooper->pollOnce(100); 197 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 198 199 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS) 200 << "elapsed time should approx. equal timeout"; 201 EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) 202 << "pollOnce result should be ALOOPER_POLL_TIMEOUT"; 203 EXPECT_EQ(0, handler.callbackCount) 204 << "callback should not have been invoked because FD was not signalled"; 205 } 206 207 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDBeforeWaiting_ImmediatelyInvokesCallbackAndReturns) { 208 Pipe pipe; 209 StubCallbackHandler handler(true); 210 211 pipe.writeSignal(); 212 handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); 213 214 StopWatch stopWatch("pollOnce"); 215 int result = mLooper->pollOnce(100); 216 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 217 218 ASSERT_EQ(OK, pipe.readSignal()) 219 << "signal should actually have been written"; 220 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) 221 << "elapsed time should be approx. zero"; 222 EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) 223 << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled"; 224 EXPECT_EQ(1, handler.callbackCount) 225 << "callback should be invoked exactly once"; 226 EXPECT_EQ(pipe.receiveFd, handler.fd) 227 << "callback should have received pipe fd as parameter"; 228 EXPECT_EQ(ALOOPER_EVENT_INPUT, handler.events) 229 << "callback should have received ALOOPER_EVENT_INPUT as events"; 230 } 231 232 TEST_F(LooperTest, PollOnce_WhenNonZeroTimeoutAndSignalledFDWhileWaiting_PromptlyInvokesCallbackAndReturns) { 233 Pipe pipe; 234 StubCallbackHandler handler(true); 235 sp<DelayedWriteSignal> delayedWriteSignal = new DelayedWriteSignal(100, & pipe); 236 237 handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); 238 delayedWriteSignal->run(); 239 240 StopWatch stopWatch("pollOnce"); 241 int result = mLooper->pollOnce(1000); 242 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 243 244 ASSERT_EQ(OK, pipe.readSignal()) 245 << "signal should actually have been written"; 246 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS) 247 << "elapsed time should approx. equal signal delay"; 248 EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) 249 << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled"; 250 EXPECT_EQ(1, handler.callbackCount) 251 << "callback should be invoked exactly once"; 252 EXPECT_EQ(pipe.receiveFd, handler.fd) 253 << "callback should have received pipe fd as parameter"; 254 EXPECT_EQ(ALOOPER_EVENT_INPUT, handler.events) 255 << "callback should have received ALOOPER_EVENT_INPUT as events"; 256 } 257 258 TEST_F(LooperTest, PollOnce_WhenCallbackAddedThenRemoved_CallbackShouldNotBeInvoked) { 259 Pipe pipe; 260 StubCallbackHandler handler(true); 261 262 handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); 263 pipe.writeSignal(); // would cause FD to be considered signalled 264 mLooper->removeFd(pipe.receiveFd); 265 266 StopWatch stopWatch("pollOnce"); 267 int result = mLooper->pollOnce(100); 268 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 269 270 ASSERT_EQ(OK, pipe.readSignal()) 271 << "signal should actually have been written"; 272 EXPECT_NEAR(100, elapsedMillis, TIMING_TOLERANCE_MS) 273 << "elapsed time should approx. equal timeout because FD was no longer registered"; 274 EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) 275 << "pollOnce result should be ALOOPER_POLL_TIMEOUT"; 276 EXPECT_EQ(0, handler.callbackCount) 277 << "callback should not be invoked"; 278 } 279 280 TEST_F(LooperTest, PollOnce_WhenCallbackReturnsFalse_CallbackShouldNotBeInvokedAgainLater) { 281 Pipe pipe; 282 StubCallbackHandler handler(false); 283 284 handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); 285 286 // First loop: Callback is registered and FD is signalled. 287 pipe.writeSignal(); 288 289 StopWatch stopWatch("pollOnce"); 290 int result = mLooper->pollOnce(0); 291 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 292 293 ASSERT_EQ(OK, pipe.readSignal()) 294 << "signal should actually have been written"; 295 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) 296 << "elapsed time should approx. equal zero because FD was already signalled"; 297 EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) 298 << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled"; 299 EXPECT_EQ(1, handler.callbackCount) 300 << "callback should be invoked"; 301 302 // Second loop: Callback is no longer registered and FD is signalled. 303 pipe.writeSignal(); 304 305 stopWatch.reset(); 306 result = mLooper->pollOnce(0); 307 elapsedMillis = ns2ms(stopWatch.elapsedTime()); 308 309 ASSERT_EQ(OK, pipe.readSignal()) 310 << "signal should actually have been written"; 311 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) 312 << "elapsed time should approx. equal zero because timeout was zero"; 313 EXPECT_EQ(ALOOPER_POLL_TIMEOUT, result) 314 << "pollOnce result should be ALOOPER_POLL_TIMEOUT"; 315 EXPECT_EQ(1, handler.callbackCount) 316 << "callback should not be invoked this time"; 317 } 318 319 TEST_F(LooperTest, PollOnce_WhenNonCallbackFdIsSignalled_ReturnsIdent) { 320 const int expectedIdent = 5; 321 void* expectedData = this; 322 323 Pipe pipe; 324 325 pipe.writeSignal(); 326 mLooper->addFd(pipe.receiveFd, expectedIdent, ALOOPER_EVENT_INPUT, NULL, expectedData); 327 328 StopWatch stopWatch("pollOnce"); 329 int fd; 330 int events; 331 void* data; 332 int result = mLooper->pollOnce(100, &fd, &events, &data); 333 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 334 335 ASSERT_EQ(OK, pipe.readSignal()) 336 << "signal should actually have been written"; 337 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) 338 << "elapsed time should be approx. zero"; 339 EXPECT_EQ(expectedIdent, result) 340 << "pollOnce result should be the ident of the FD that was signalled"; 341 EXPECT_EQ(pipe.receiveFd, fd) 342 << "pollOnce should have returned the received pipe fd"; 343 EXPECT_EQ(ALOOPER_EVENT_INPUT, events) 344 << "pollOnce should have returned ALOOPER_EVENT_INPUT as events"; 345 EXPECT_EQ(expectedData, data) 346 << "pollOnce should have returned the data"; 347 } 348 349 TEST_F(LooperTest, AddFd_WhenCallbackAdded_ReturnsOne) { 350 Pipe pipe; 351 int result = mLooper->addFd(pipe.receiveFd, 0, ALOOPER_EVENT_INPUT, NULL, NULL); 352 353 EXPECT_EQ(1, result) 354 << "addFd should return 1 because FD was added"; 355 } 356 357 TEST_F(LooperTest, AddFd_WhenIdentIsNegativeAndCallbackIsNull_ReturnsError) { 358 Pipe pipe; 359 int result = mLooper->addFd(pipe.receiveFd, -1, ALOOPER_EVENT_INPUT, NULL, NULL); 360 361 EXPECT_EQ(-1, result) 362 << "addFd should return -1 because arguments were invalid"; 363 } 364 365 TEST_F(LooperTest, AddFd_WhenNoCallbackAndAllowNonCallbacksIsFalse_ReturnsError) { 366 Pipe pipe; 367 sp<Looper> looper = new Looper(false /*allowNonCallbacks*/); 368 int result = looper->addFd(pipe.receiveFd, 0, 0, NULL, NULL); 369 370 EXPECT_EQ(-1, result) 371 << "addFd should return -1 because arguments were invalid"; 372 } 373 374 TEST_F(LooperTest, RemoveFd_WhenCallbackNotAdded_ReturnsZero) { 375 int result = mLooper->removeFd(1); 376 377 EXPECT_EQ(0, result) 378 << "removeFd should return 0 because FD not registered"; 379 } 380 381 TEST_F(LooperTest, RemoveFd_WhenCallbackAddedThenRemovedTwice_ReturnsOnceFirstTimeAndReturnsZeroSecondTime) { 382 Pipe pipe; 383 StubCallbackHandler handler(false); 384 handler.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); 385 386 // First time. 387 int result = mLooper->removeFd(pipe.receiveFd); 388 389 EXPECT_EQ(1, result) 390 << "removeFd should return 1 first time because FD was registered"; 391 392 // Second time. 393 result = mLooper->removeFd(pipe.receiveFd); 394 395 EXPECT_EQ(0, result) 396 << "removeFd should return 0 second time because FD was no longer registered"; 397 } 398 399 TEST_F(LooperTest, PollOnce_WhenCallbackAddedTwice_OnlySecondCallbackShouldBeInvoked) { 400 Pipe pipe; 401 StubCallbackHandler handler1(true); 402 StubCallbackHandler handler2(true); 403 404 handler1.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); 405 handler2.setCallback(mLooper, pipe.receiveFd, ALOOPER_EVENT_INPUT); // replace it 406 pipe.writeSignal(); // would cause FD to be considered signalled 407 408 StopWatch stopWatch("pollOnce"); 409 int result = mLooper->pollOnce(100); 410 int32_t elapsedMillis = ns2ms(stopWatch.elapsedTime()); 411 412 ASSERT_EQ(OK, pipe.readSignal()) 413 << "signal should actually have been written"; 414 EXPECT_NEAR(0, elapsedMillis, TIMING_TOLERANCE_MS) 415 << "elapsed time should approx. zero because FD was already signalled"; 416 EXPECT_EQ(ALOOPER_POLL_CALLBACK, result) 417 << "pollOnce result should be ALOOPER_POLL_CALLBACK because FD was signalled"; 418 EXPECT_EQ(0, handler1.callbackCount) 419 << "original handler callback should not be invoked because it was replaced"; 420 EXPECT_EQ(1, handler2.callbackCount) 421 << "replacement handler callback should be invoked"; 422 } 423 424 425 } // namespace android 426