Home | History | Annotate | Download | only in util
      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 com.android.internal.util;
     18 
     19 import static org.junit.Assert.*;
     20 import static org.mockito.Mockito.*;
     21 
     22 import android.app.AlarmManager;
     23 import android.content.Context;
     24 import android.os.Handler;
     25 import android.os.Looper;
     26 import android.os.Message;
     27 import android.test.suitebuilder.annotation.SmallTest;
     28 
     29 import org.junit.After;
     30 import org.junit.Before;
     31 import org.junit.Test;
     32 import org.mockito.ArgumentCaptor;
     33 import org.mockito.Mock;
     34 import org.mockito.MockitoAnnotations;
     35 import org.mockito.Spy;
     36 import org.mockito.invocation.InvocationOnMock;
     37 import org.mockito.stubbing.Answer;
     38 
     39 /**
     40  * Unit tests for {@link com.android.internal.util.WakeupMessage}.
     41  */
     42 @SmallTest
     43 public class WakeupMessageTest {
     44     private static final String TEST_CMD_NAME = "TEST cmd Name";
     45     private static final int TEST_CMD = 18;
     46     private static final int TEST_ARG1 = 33;
     47     private static final int TEST_ARG2 = 182;
     48     private static final Object TEST_OBJ = "hello";
     49 
     50     @Mock AlarmManager mAlarmManager;
     51     WakeupMessage mMessage;
     52     // Make a spy so that we can verify calls to it
     53     @Spy MessageCapturingHandler mHandler = new MessageCapturingHandler();
     54 
     55     ArgumentCaptor<AlarmManager.OnAlarmListener> mListenerCaptor =
     56             ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
     57 
     58     /**
     59      * A Handler that will capture the most recent message sent to it.
     60      *
     61      * This handler is setup on the main Looper
     62      */
     63     public static class MessageCapturingHandler extends Handler {
     64         private Message mLastMessage;
     65 
     66         public MessageCapturingHandler() {
     67             super(Looper.getMainLooper(), /* Nothing is actually dispatched on this Looper */
     68                     null, false);
     69         }
     70 
     71         @Override
     72         public void handleMessage(Message m) {
     73             // need to copy since it will be recycled after this method returns
     74             mLastMessage = Message.obtain(m);
     75         }
     76 
     77         public Message getLastMessage() {
     78             return mLastMessage;
     79         }
     80     }
     81 
     82     /**
     83      * Sets up the test.
     84      */
     85     @Before
     86     public void setUp() {
     87         MockitoAnnotations.initMocks(this);
     88 
     89         Context context = mock(Context.class);
     90         when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
     91         // capture the listener for each AlarmManager.setExact call
     92         doNothing().when(mAlarmManager).setExact(anyInt(), anyLong(), any(String.class),
     93                 mListenerCaptor.capture(), any(Handler.class));
     94 
     95         mMessage = new WakeupMessage(context, mHandler, TEST_CMD_NAME, TEST_CMD, TEST_ARG1,
     96                 TEST_ARG2, TEST_OBJ);
     97     }
     98 
     99     /**
    100      * Ensure the test is cleaned up and ready for the next test.
    101      */
    102     @After
    103     public void cleanup() {
    104         validateMockitoUsage();
    105     }
    106 
    107     private void scheduleAndVerifyAlarm(long when) {
    108         mMessage.schedule(when);
    109         verify(mAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(when),
    110                 eq(TEST_CMD_NAME), any(AlarmManager.OnAlarmListener.class), eq(mHandler));
    111     }
    112 
    113     private void verifyMessageDispatchedOnce() {
    114         verify(mHandler, times(1)).handleMessage(any(Message.class));
    115         assertEquals("what", TEST_CMD, mHandler.getLastMessage().what);
    116         assertEquals("arg1", TEST_ARG1, mHandler.getLastMessage().arg1);
    117         assertEquals("arg2", TEST_ARG2, mHandler.getLastMessage().arg2);
    118         assertEquals("obj", TEST_OBJ, mHandler.getLastMessage().obj);
    119     }
    120 
    121     /**
    122      * Schedule and deliver a single message
    123      */
    124     @Test
    125     public void scheduleAndDeliverMessage() {
    126         final long when = 1001;
    127         scheduleAndVerifyAlarm(when);
    128         verify(mHandler, never()).handleMessage(any(Message.class));
    129         mListenerCaptor.getValue().onAlarm();
    130         verifyMessageDispatchedOnce();
    131     }
    132 
    133     /**
    134      * Check that the message is not delivered if cancel is called it after its alarm fires but
    135      * before onAlarm is called.
    136      *
    137      * This ensures that if cancel is called on the handler thread, any previously-scheduled message
    138      * is guaranteed not to be delivered.
    139      */
    140     @Test
    141     public void scheduleAndCancelMessage() {
    142         final long when = 1010;
    143         scheduleAndVerifyAlarm(when);
    144         mMessage.cancel();
    145         mListenerCaptor.getValue().onAlarm();
    146         verify(mHandler, never()).handleMessage(any(Message.class));
    147     }
    148 
    149     /**
    150      * Verify nothing happens when cancel is called without a schedule
    151      */
    152     @Test
    153     public void cancelWithoutSchedule() {
    154         mMessage.cancel();
    155     }
    156 
    157     /**
    158      * Verify that the message is silently rescheduled if schedule is called twice without the
    159      * message being dispatched first.
    160      */
    161     @Test
    162     public void scheduleTwiceWithoutMessageDispatched() {
    163         final long when1 = 1011;
    164         final long when2 = 1012;
    165         scheduleAndVerifyAlarm(when1);
    166         scheduleAndVerifyAlarm(when2);
    167         mListenerCaptor.getValue().onAlarm();
    168         verifyMessageDispatchedOnce();
    169     }
    170 
    171 }
    172