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