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