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.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
     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
     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
    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
    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
    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
    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
    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
    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)
    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)
    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
    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)
    367     public void testAutoDispatchThrowsExceptionWhenNoMessagesDispatched() {
    368         mTestLooper.startAutoDispatch();
    369         mTestLooper.stopAutoDispatch();
    370     }
    371 }
    372