/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package com.android.internal.telephony;
import android.content.Context;
import android.content.Intent;
import android.os.HandlerThread;
import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.android.internal.telephony.cat.*;
import com.android.internal.telephony.TelephonyTestUtils;
import com.android.internal.telephony.uicc.IccFileHandler;
import com.android.internal.telephony.uicc.UiccCard;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import static org.junit.Assert.*;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import java.lang.reflect.Method;
import junit.framework.Assert;
public class CatServiceTest extends TelephonyTest {
private static final int SINGLE_SIM = 1;
private TelephonyManager mTelephonyManager;
private CatService mCatService;
@Mock
private UiccCard mMockUiccCard;
@Mock
private IccFileHandler mIccFileHandler;
/* CatService extends handler and to instantiate the object within this test,
* we will need a looper to be ready. The HandlerThread here is used for this. The .start()
* is invoked in the setUp() call and the CatService is initialized in the
* onLooperPrepared() callback.
*
* This will not be required if the class under test is not extending Handler
*/
private class CatServiceTestHandler extends HandlerThread {
private CatServiceTestHandler(String name) {
super(name);
}
@Override
public void onLooperPrepared() {
mCatService = CatService.getInstance(
mSimulatedCommands, mContext, mMockUiccCard, 0);
setReady(true);
}
}
@Before
public void setUp() throws Exception {
super.setUp(this.getClass().getSimpleName());
mTelephonyManager = (TelephonyManager) mContext.getSystemService(
Context.TELEPHONY_SERVICE);
/* These are preconditions for the tests, all the APIs that the Class Under Test
* will invoke, has to be setup here using dummy values
*/
doReturn(SINGLE_SIM).when(mTelephonyManager).getSimCount();
doReturn(SINGLE_SIM).when(mTelephonyManager).getPhoneCount();
/* Some of the objects are already provided by the base class and a subset of it
* which is required for the CatService test will be used as dummy responses
* when the Class Under Test will invoke it in its constructor or in the methods
* under test
*/
doReturn(mUiccCardApplication3gpp).when(mMockUiccCard).getApplicationIndex(0);
doReturn(mIccFileHandler).when(mUiccCardApplication3gpp).getIccFileHandler();
doReturn(mSimRecords).when(mUiccCardApplication3gpp).getIccRecords();
/* Kick off the handler thread, which leads to instantiation of the CatService object */
new CatServiceTestHandler(TAG).start();
waitUntilReady();
}
@After
public void tearDown() throws Exception {
super.tearDown();
mTelephonyManager = null;
mCatService.dispose();
}
@Test @SmallTest
public void isSupportedSetupEventCommand() {
assertNotNull(mCatService);
/* Create a mock object to be sent to method under test */
CatCmdMessage mockCatMsg = mock(CatCmdMessage.class);
/* Create a real object that will returned when getSetEventList() is invoked
* on the mock object
*/
CatCmdMessage.SetupEventListSettings eventListSettings =
mockCatMsg.new SetupEventListSettings();
/* Define the mock behavior for getSetEventList(), to return the real object created */
Mockito.when(mockCatMsg.getSetEventList()).thenReturn(eventListSettings);
eventListSettings.eventList =
new int[]{CatCmdMessage.SetupEventListConstants.LANGUAGE_SELECTION_EVENT};
assertEquals(true, callIsSupportedSetupEventCommand(mockCatMsg));
eventListSettings.eventList =
new int[]{CatCmdMessage.SetupEventListConstants.HCI_CONNECTIVITY_EVENT};
assertEquals(true, callIsSupportedSetupEventCommand(mockCatMsg));
}
/* Wrapper function that uses reflection to invoke private methods */
private boolean callIsSupportedSetupEventCommand(CatCmdMessage mockCatMsg) {
Class clsParams[] = new Class[1];
clsParams[0] = CatCmdMessage.class;
Object params[] = new Object[1];
params[0] = mockCatMsg;
return (boolean)invokeNonStaticMethod(CatService.class, mCatService,
"isSupportedSetupEventCommand", clsParams, params);
}
/* In this test the method under test creates an intent,
* sets a flag and broadcasts it, this test ensures the flag is set
*/
@Test
public void broadcastCatCmdIntent() {
CatCmdMessage mockCatMsg = mock(CatCmdMessage.class);
Class clsParams[] = new Class[1];
clsParams[0] = CatCmdMessage.class;
Object params[] = new Object[1];
params[0] = mockCatMsg;
/* broadcastCatCmdIntent method will get tested and 'sendBroadcast' would get invoked */
invokeNonStaticMethod(CatService.class, mCatService,
"broadcastCatCmdIntent", clsParams, params);
/* Since mock Context is used, sendBroadcast method is trapped
* and arguments can be examined. In the example below, first argument is an
* intent and is captured and examined for the flag. Parameters of no interest can
* be left as anyInt() or anyString() based on the method signature
*/
ArgumentCaptor<Intent> intentCapture = ArgumentCaptor.forClass(Intent.class);
Mockito.verify(mContext).sendBroadcast(intentCapture.capture(), Mockito.anyString());
assertEquals(
((Intent)intentCapture.getValue()).getFlags() & Intent.FLAG_RECEIVER_FOREGROUND,
Intent.FLAG_RECEIVER_FOREGROUND);
}
@Test
public void handleSessionEnd() {
invokeNonStaticMethod(CatService.class, mCatService, "handleSessionEnd", null, null);
ArgumentCaptor<Intent> intentCapture = ArgumentCaptor.forClass(Intent.class);
Mockito.verify(mContext).sendBroadcast(intentCapture.capture(), Mockito.anyString());
assertEquals(
((Intent)intentCapture.getValue()).getFlags() & Intent.FLAG_RECEIVER_FOREGROUND,
Intent.FLAG_RECEIVER_FOREGROUND);
}
private Object invokeNonStaticMethod(Class clazz, Object caller, String method,
Class[] clsParams, Object[] params) {
try {
Method methodReflection = clazz.getDeclaredMethod(method, clsParams);
methodReflection.setAccessible(true);
return methodReflection.invoke(caller, params);
} catch (Exception e) {
Assert.fail(e.toString());
return null;
}
}
}