blob: 7935880d12a914836767ba8b912af94d14015846 [file] [log] [blame]
/*
* Copyright (C) 2016 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.util;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import android.app.AlarmManager;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
/**
* Unit tests for {@link com.android.internal.util.WakeupMessage}.
*/
@SmallTest
public class WakeupMessageTest {
private static final String TEST_CMD_NAME = "TEST cmd Name";
private static final int TEST_CMD = 18;
private static final int TEST_ARG1 = 33;
private static final int TEST_ARG2 = 182;
private static final Object TEST_OBJ = "hello";
@Mock AlarmManager mAlarmManager;
WakeupMessage mMessage;
// Make a spy so that we can verify calls to it
@Spy MessageCapturingHandler mHandler = new MessageCapturingHandler();
ArgumentCaptor<AlarmManager.OnAlarmListener> mListenerCaptor =
ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
/**
* A Handler that will capture the most recent message sent to it.
*
* This handler is setup on the main Looper
*/
public static class MessageCapturingHandler extends Handler {
private Message mLastMessage;
public MessageCapturingHandler() {
super(Looper.getMainLooper(), /* Nothing is actually dispatched on this Looper */
null, false);
}
@Override
public void handleMessage(Message m) {
// need to copy since it will be recycled after this method returns
mLastMessage = Message.obtain(m);
}
public Message getLastMessage() {
return mLastMessage;
}
}
/**
* Sets up the test.
*/
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Context context = mock(Context.class);
when(context.getSystemService(Context.ALARM_SERVICE)).thenReturn(mAlarmManager);
// capture the listener for each AlarmManager.setExact call
doNothing().when(mAlarmManager).setExact(anyInt(), anyLong(), any(String.class),
mListenerCaptor.capture(), any(Handler.class));
mMessage = new WakeupMessage(context, mHandler, TEST_CMD_NAME, TEST_CMD, TEST_ARG1,
TEST_ARG2, TEST_OBJ);
}
/**
* Ensure the test is cleaned up and ready for the next test.
*/
@After
public void cleanup() {
validateMockitoUsage();
}
private void scheduleAndVerifyAlarm(long when) {
mMessage.schedule(when);
verify(mAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME_WAKEUP), eq(when),
eq(TEST_CMD_NAME), any(AlarmManager.OnAlarmListener.class), eq(mHandler));
}
private void verifyMessageDispatchedOnce() {
verify(mHandler, times(1)).handleMessage(any(Message.class));
assertEquals("what", TEST_CMD, mHandler.getLastMessage().what);
assertEquals("arg1", TEST_ARG1, mHandler.getLastMessage().arg1);
assertEquals("arg2", TEST_ARG2, mHandler.getLastMessage().arg2);
assertEquals("obj", TEST_OBJ, mHandler.getLastMessage().obj);
}
/**
* Schedule and deliver a single message
*/
@Test
public void scheduleAndDeliverMessage() {
final long when = 1001;
scheduleAndVerifyAlarm(when);
verify(mHandler, never()).handleMessage(any(Message.class));
mListenerCaptor.getValue().onAlarm();
verifyMessageDispatchedOnce();
}
/**
* Check that the message is not delivered if cancel is called it after its alarm fires but
* before onAlarm is called.
*
* This ensures that if cancel is called on the handler thread, any previously-scheduled message
* is guaranteed not to be delivered.
*/
@Test
public void scheduleAndCancelMessage() {
final long when = 1010;
scheduleAndVerifyAlarm(when);
mMessage.cancel();
mListenerCaptor.getValue().onAlarm();
verify(mHandler, never()).handleMessage(any(Message.class));
}
/**
* Verify nothing happens when cancel is called without a schedule
*/
@Test
public void cancelWithoutSchedule() {
mMessage.cancel();
}
/**
* Verify that the message is silently rescheduled if schedule is called twice without the
* message being dispatched first.
*/
@Test
public void scheduleTwiceWithoutMessageDispatched() {
final long when1 = 1011;
final long when2 = 1012;
scheduleAndVerifyAlarm(when1);
scheduleAndVerifyAlarm(when2);
mListenerCaptor.getValue().onAlarm();
verifyMessageDispatchedOnce();
}
}