1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.os.test; 18 19 import static org.hamcrest.core.IsEqual.equalTo; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertTrue; 22 import static org.mockito.Matchers.any; 23 import static org.mockito.Mockito.inOrder; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.never; 26 import static org.mockito.Mockito.spy; 27 28 import android.os.Handler; 29 import android.os.Looper; 30 import android.os.Message; 31 import android.test.suitebuilder.annotation.SmallTest; 32 33 import org.junit.Before; 34 import org.junit.Rule; 35 import org.junit.Test; 36 import org.junit.rules.ErrorCollector; 37 import org.mockito.ArgumentCaptor; 38 import org.mockito.InOrder; 39 import org.mockito.MockitoAnnotations; 40 41 import java.util.concurrent.Executor; 42 43 /** 44 * Test TestLooperAbstractTime which provides control over "time". Note that 45 * real-time is being used as well. Therefore small time increments are NOT 46 * reliable. All tests are in "K" units (i.e. *1000). 47 */ 48 49 @SmallTest 50 public class TestLooperTest { 51 private TestLooper mTestLooper; 52 private Handler mHandler; 53 private Handler mHandlerSpy; 54 private Executor mExecutor; 55 56 @Rule 57 public ErrorCollector collector = new ErrorCollector(); 58 59 @Before 60 public void setUp() throws Exception { 61 MockitoAnnotations.initMocks(this); 62 63 mTestLooper = new TestLooper(); 64 mHandler = new Handler(mTestLooper.getLooper()); 65 mHandlerSpy = spy(mHandler); 66 mExecutor = mTestLooper.getNewExecutor(); 67 } 68 69 /** 70 * Basic test with no time stamps: dispatch 4 messages, check that all 4 71 * delivered (in correct order). 72 */ 73 @Test 74 public void testNoTimeMovement() { 75 final int messageA = 1; 76 final int messageB = 2; 77 final int messageC = 3; 78 79 InOrder inOrder = inOrder(mHandlerSpy); 80 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 81 82 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA)); 83 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA)); 84 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB)); 85 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageC)); 86 mTestLooper.dispatchAll(); 87 88 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 89 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what)); 90 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 91 collector.checkThat("2: messageA", messageA, equalTo(messageCaptor.getValue().what)); 92 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 93 collector.checkThat("3: messageB", messageB, equalTo(messageCaptor.getValue().what)); 94 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 95 collector.checkThat("4: messageC", messageC, equalTo(messageCaptor.getValue().what)); 96 97 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class)); 98 } 99 100 /** 101 * Basic test of the Executor with no time stamps: dispatch 4 executables, check that all 4 102 * executed in correct order. 103 */ 104 @Test 105 public void testNoTimeMovementExecutor() { 106 final Runnable runnableA = mock(Runnable.class); 107 final Runnable runnableB = mock(Runnable.class); 108 final Runnable runnableC = mock(Runnable.class); 109 110 InOrder inOrder = inOrder(runnableA, runnableB, runnableC); 111 112 mExecutor.execute(runnableA); 113 mExecutor.execute(runnableB); 114 mExecutor.execute(runnableA); 115 mExecutor.execute(runnableC); 116 mTestLooper.dispatchAll(); 117 118 inOrder.verify(runnableA).run(); 119 inOrder.verify(runnableB).run(); 120 inOrder.verify(runnableA).run(); 121 inOrder.verify(runnableC).run(); 122 123 inOrder.verifyNoMoreInteractions(); 124 } 125 126 /** 127 * Test message sequence: A, B, C@5K, A@10K. Don't move time. 128 * <p> 129 * Expected: only get A, B 130 */ 131 @Test 132 public void testDelayedDispatchNoTimeMove() { 133 final int messageA = 1; 134 final int messageB = 2; 135 final int messageC = 3; 136 137 InOrder inOrder = inOrder(mHandlerSpy); 138 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 139 140 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA)); 141 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB)); 142 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000); 143 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 10000); 144 mTestLooper.dispatchAll(); 145 146 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 147 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what)); 148 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 149 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what)); 150 151 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class)); 152 } 153 154 /** 155 * Test message sequence: A, B, C@5K, A@10K, Advance time by 5K. 156 * <p> 157 * Expected: only get A, B, C 158 */ 159 @Test 160 public void testDelayedDispatchAdvanceTimeOnce() { 161 final int messageA = 1; 162 final int messageB = 2; 163 final int messageC = 3; 164 165 InOrder inOrder = inOrder(mHandlerSpy); 166 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 167 168 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA)); 169 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB)); 170 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000); 171 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 10000); 172 mTestLooper.moveTimeForward(5000); 173 mTestLooper.dispatchAll(); 174 175 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 176 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what)); 177 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 178 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what)); 179 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 180 collector.checkThat("3: messageC", messageC, equalTo(messageCaptor.getValue().what)); 181 182 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class)); 183 } 184 185 /** 186 * Test message sequence: A, B, C@5K, Advance time by 4K, A@1K, B@2K Advance 187 * time by 1K. 188 * <p> 189 * Expected: get A, B, C, A 190 */ 191 @Test 192 public void testDelayedDispatchAdvanceTimeTwice() { 193 final int messageA = 1; 194 final int messageB = 2; 195 final int messageC = 3; 196 197 InOrder inOrder = inOrder(mHandlerSpy); 198 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 199 200 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA)); 201 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB)); 202 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000); 203 mTestLooper.moveTimeForward(4000); 204 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 1000); 205 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageB), 2000); 206 mTestLooper.moveTimeForward(1000); 207 mTestLooper.dispatchAll(); 208 209 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 210 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what)); 211 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 212 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what)); 213 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 214 collector.checkThat("3: messageC", messageC, equalTo(messageCaptor.getValue().what)); 215 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 216 collector.checkThat("4: messageA", messageA, equalTo(messageCaptor.getValue().what)); 217 218 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class)); 219 } 220 221 /** 222 * Test message sequence: A, B, C@5K, Advance time by 4K, A@5K, B@2K Advance 223 * time by 3K. 224 * <p> 225 * Expected: get A, B, C, B 226 */ 227 @Test 228 public void testDelayedDispatchReverseOrder() { 229 final int messageA = 1; 230 final int messageB = 2; 231 final int messageC = 3; 232 233 InOrder inOrder = inOrder(mHandlerSpy); 234 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 235 236 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA)); 237 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB)); 238 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000); 239 mTestLooper.moveTimeForward(4000); 240 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 5000); 241 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageB), 2000); 242 mTestLooper.moveTimeForward(3000); 243 mTestLooper.dispatchAll(); 244 245 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 246 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what)); 247 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 248 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what)); 249 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 250 collector.checkThat("3: messageC", messageC, equalTo(messageCaptor.getValue().what)); 251 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 252 collector.checkThat("4: messageB", messageB, equalTo(messageCaptor.getValue().what)); 253 254 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class)); 255 } 256 257 /** 258 * Test message sequence: A, B, C@5K, Advance time by 4K, dispatch all, 259 * A@5K, B@2K Advance time by 3K, dispatch all. 260 * <p> 261 * Expected: get A, B after first dispatch; then C, B after second dispatch 262 */ 263 @Test 264 public void testDelayedDispatchAllMultipleTimes() { 265 final int messageA = 1; 266 final int messageB = 2; 267 final int messageC = 3; 268 269 InOrder inOrder = inOrder(mHandlerSpy); 270 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 271 272 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA)); 273 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageB)); 274 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageC), 5000); 275 mTestLooper.moveTimeForward(4000); 276 mTestLooper.dispatchAll(); 277 278 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 279 collector.checkThat("1: messageA", messageA, equalTo(messageCaptor.getValue().what)); 280 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 281 collector.checkThat("2: messageB", messageB, equalTo(messageCaptor.getValue().what)); 282 283 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageA), 5000); 284 mHandlerSpy.sendMessageDelayed(mHandler.obtainMessage(messageB), 2000); 285 mTestLooper.moveTimeForward(3000); 286 mTestLooper.dispatchAll(); 287 288 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 289 collector.checkThat("3: messageC", messageC, equalTo(messageCaptor.getValue().what)); 290 inOrder.verify(mHandlerSpy).handleMessage(messageCaptor.capture()); 291 collector.checkThat("4: messageB", messageB, equalTo(messageCaptor.getValue().what)); 292 293 inOrder.verify(mHandlerSpy, never()).handleMessage(any(Message.class)); 294 } 295 296 /** 297 * Test AutoDispatch for a single message. 298 * This test would ideally use the Channel sendMessageSynchronously. At this time, the setup to 299 * get a working test channel is cumbersome. Until this is fixed, we substitute with a 300 * sendMessage followed by a blocking call. The main test thread blocks until the test handler 301 * receives the test message (messageA) and sets a boolean true. Once the boolean is true, the 302 * main thread will exit the busy wait loop, stop autoDispatch and check the assert. 303 * 304 * Enable AutoDispatch, add message, block on message being handled and stop AutoDispatch. 305 * <p> 306 * Expected: handleMessage is called for messageA and stopAutoDispatch is called. 307 */ 308 @Test 309 public void testAutoDispatchWithSingleMessage() { 310 final int mLoopSleepTimeMs = 5; 311 312 final int messageA = 1; 313 314 TestLooper mockLooper = new TestLooper(); 315 class TestHandler extends Handler { 316 public volatile boolean handledMessage = false; 317 TestHandler(Looper looper) { 318 super(looper); 319 } 320 321 @Override 322 public void handleMessage(Message msg) { 323 if (msg.what == messageA) { 324 handledMessage = true; 325 } 326 } 327 } 328 329 TestHandler testHandler = new TestHandler(mockLooper.getLooper()); 330 mockLooper.startAutoDispatch(); 331 testHandler.sendMessage(testHandler.obtainMessage(messageA)); 332 while (!testHandler.handledMessage) { 333 // Block until message is handled 334 try { 335 Thread.sleep(mLoopSleepTimeMs); 336 } catch (InterruptedException e) { 337 // Interrupted while sleeping. 338 } 339 } 340 mockLooper.stopAutoDispatch(); 341 assertTrue("TestHandler should have received messageA", testHandler.handledMessage); 342 } 343 344 /** 345 * Test starting AutoDispatch while already running throws IllegalStateException 346 * Enable AutoDispatch two times in a row. 347 * <p> 348 * Expected: catch IllegalStateException on second call. 349 */ 350 @Test(expected = IllegalStateException.class) 351 public void testRepeatedStartAutoDispatchThrowsException() { 352 mTestLooper.startAutoDispatch(); 353 mTestLooper.startAutoDispatch(); 354 } 355 356 /** 357 * Test stopping AutoDispatch without previously starting throws IllegalStateException 358 * Stop AutoDispatch 359 * <p> 360 * Expected: catch IllegalStateException on second call. 361 */ 362 @Test(expected = IllegalStateException.class) 363 public void testStopAutoDispatchWithoutStartThrowsException() { 364 mTestLooper.stopAutoDispatch(); 365 } 366 367 /** 368 * Test AutoDispatch exits and does not dispatch a later message. 369 * Start and stop AutoDispatch then add a message. 370 * <p> 371 * Expected: After AutoDispatch is stopped, dispatchAll will return 1. 372 */ 373 @Test 374 public void testAutoDispatchStopsCleanlyWithoutDispatchingAMessage() { 375 final int messageA = 1; 376 377 InOrder inOrder = inOrder(mHandlerSpy); 378 ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); 379 380 mTestLooper.startAutoDispatch(); 381 try { 382 mTestLooper.stopAutoDispatch(); 383 } catch (IllegalStateException e) { 384 // Stopping without a dispatch will throw an exception. 385 } 386 387 mHandlerSpy.sendMessage(mHandler.obtainMessage(messageA)); 388 assertEquals("One message should be dispatched", 1, mTestLooper.dispatchAll()); 389 } 390 391 /** 392 * Test AutoDispatch throws an exception when no messages are dispatched. 393 * Start and stop AutoDispatch 394 * <p> 395 * Expected: Exception is thrown with the stopAutoDispatch call. 396 */ 397 @Test(expected = IllegalStateException.class) 398 public void testAutoDispatchThrowsExceptionWhenNoMessagesDispatched() { 399 mTestLooper.startAutoDispatch(); 400 mTestLooper.stopAutoDispatch(); 401 } 402 } 403