Home | History | Annotate | Download | only in test
      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