Add unit tests for TetherService.
BUG: 26247383 Change-Id: I07ce14f4a2726e35b8b5665a3e0a8df7af864b3b
This commit is contained in:
@@ -37,6 +37,7 @@ import android.text.TextUtils;
|
|||||||
import android.util.ArrayMap;
|
import android.util.ArrayMap;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.settingslib.TetherUtil;
|
import com.android.settingslib.TetherUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -46,7 +47,8 @@ public class TetherService extends Service {
|
|||||||
private static final String TAG = "TetherService";
|
private static final String TAG = "TetherService";
|
||||||
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
|
||||||
private static final String EXTRA_RESULT = "EntitlementResult";
|
@VisibleForTesting
|
||||||
|
public static final String EXTRA_RESULT = "EntitlementResult";
|
||||||
|
|
||||||
// Activity results to match the activity provision protocol.
|
// Activity results to match the activity provision protocol.
|
||||||
// Default to something not ok.
|
// Default to something not ok.
|
||||||
@@ -295,7 +297,7 @@ public class TetherService extends Service {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceive(Context context, Intent intent) {
|
public void onReceive(Context context, Intent intent) {
|
||||||
if (DEBUG) Log.d(TAG, "Got provision result " + intent);
|
if (DEBUG) Log.d(TAG, "Got provision result " + intent);
|
||||||
String provisionResponse = context.getResources().getString(
|
String provisionResponse = getResources().getString(
|
||||||
com.android.internal.R.string.config_mobile_hotspot_provision_response);
|
com.android.internal.R.string.config_mobile_hotspot_provision_response);
|
||||||
|
|
||||||
if (provisionResponse.equals(intent.getAction())) {
|
if (provisionResponse.equals(intent.getAction())) {
|
||||||
|
358
tests/unit/src/com/android/settings/TetherServiceTest.java
Normal file
358
tests/unit/src/com/android/settings/TetherServiceTest.java
Normal file
@@ -0,0 +1,358 @@
|
|||||||
|
/*
|
||||||
|
* 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.settings;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
import static org.mockito.Matchers.*;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static android.net.ConnectivityManager.EXTRA_ADD_TETHER_TYPE;
|
||||||
|
import static android.net.ConnectivityManager.EXTRA_PROVISION_CALLBACK;
|
||||||
|
import static android.net.ConnectivityManager.EXTRA_REM_TETHER_TYPE;
|
||||||
|
import static android.net.ConnectivityManager.EXTRA_RUN_PROVISION;
|
||||||
|
import static android.net.ConnectivityManager.EXTRA_SET_ALARM;
|
||||||
|
import static android.net.ConnectivityManager.TETHERING_BLUETOOTH;
|
||||||
|
import static android.net.ConnectivityManager.TETHERING_INVALID;
|
||||||
|
import static android.net.ConnectivityManager.TETHERING_USB;
|
||||||
|
import static android.net.ConnectivityManager.TETHERING_WIFI;
|
||||||
|
import static android.net.ConnectivityManager.TETHER_ERROR_NO_ERROR;
|
||||||
|
import static android.net.ConnectivityManager.TETHER_ERROR_PROVISION_FAILED;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlarmManager;
|
||||||
|
import android.app.PendingIntent;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.ContextWrapper;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.content.SharedPreferences.Editor;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.wifi.WifiConfiguration;
|
||||||
|
import android.net.wifi.WifiManager;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
|
import android.os.SystemClock;
|
||||||
|
import android.test.ServiceTestCase;
|
||||||
|
import android.test.mock.MockResources;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.android.settings.TetherService;
|
||||||
|
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
import org.mockito.Captor;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
|
public class TetherServiceTest extends ServiceTestCase<TetherService> {
|
||||||
|
|
||||||
|
private static final String TAG = "TetherServiceTest";
|
||||||
|
private static final String TEST_RESPONSE_ACTION = "testProvisioningResponseAction";
|
||||||
|
private static final String TEST_NO_UI_ACTION = "testNoUiProvisioningRequestAction";
|
||||||
|
private static final int BOGUS_RECEIVER_RESULT = -5;
|
||||||
|
private static final int TEST_CHECK_PERIOD = 100;
|
||||||
|
private static final int MS_PER_HOUR = 60 * 60 * 1000;
|
||||||
|
private static final int SHORT_TIMEOUT = 100;
|
||||||
|
private static final int PROVISION_TIMEOUT = 1000;
|
||||||
|
|
||||||
|
private TetherService mService;
|
||||||
|
private MockResources mResources;
|
||||||
|
int mLastReceiverResultCode = BOGUS_RECEIVER_RESULT;
|
||||||
|
private int mLastTetherRequestType = TETHERING_INVALID;
|
||||||
|
private int mProvisionResponse = BOGUS_RECEIVER_RESULT;
|
||||||
|
private ProvisionReceiver mProvisionReceiver;
|
||||||
|
private Receiver mResultReceiver;
|
||||||
|
|
||||||
|
@Mock private AlarmManager mAlarmManager;
|
||||||
|
@Mock private ConnectivityManager mConnectivityManager;
|
||||||
|
@Mock private WifiManager mWifiManager;
|
||||||
|
@Mock private SharedPreferences mPrefs;
|
||||||
|
@Mock private Editor mPrefEditor;
|
||||||
|
@Captor private ArgumentCaptor<PendingIntent> mPiCaptor;
|
||||||
|
@Captor private ArgumentCaptor<String> mStoredTypes;
|
||||||
|
|
||||||
|
public TetherServiceTest() {
|
||||||
|
super(TetherService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
MockitoAnnotations.initMocks(this);
|
||||||
|
|
||||||
|
mResources = new MockResources();
|
||||||
|
mContext = new TestContextWrapper(getContext());
|
||||||
|
setContext(mContext);
|
||||||
|
|
||||||
|
mResultReceiver = new Receiver(this);
|
||||||
|
mLastReceiverResultCode = BOGUS_RECEIVER_RESULT;
|
||||||
|
mProvisionResponse = Activity.RESULT_OK;
|
||||||
|
mProvisionReceiver = new ProvisionReceiver();
|
||||||
|
IntentFilter filter = new IntentFilter(TEST_NO_UI_ACTION);
|
||||||
|
filter.addCategory(Intent.CATEGORY_DEFAULT);
|
||||||
|
mContext.registerReceiver(mProvisionReceiver, filter);
|
||||||
|
|
||||||
|
final String CURRENT_TYPES = "currentTethers";
|
||||||
|
when(mPrefs.getString(CURRENT_TYPES, "")).thenReturn("");
|
||||||
|
when(mPrefs.edit()).thenReturn(mPrefEditor);
|
||||||
|
when(mPrefEditor.putString(eq(CURRENT_TYPES), mStoredTypes.capture())).thenReturn(
|
||||||
|
mPrefEditor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void tearDown() throws Exception {
|
||||||
|
mContext.unregisterReceiver(mProvisionReceiver);
|
||||||
|
super.tearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelAllProvisioning() {
|
||||||
|
int[] types = new int[]{TETHERING_BLUETOOTH, TETHERING_WIFI, TETHERING_USB};
|
||||||
|
for (int type : types) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtra(EXTRA_REM_TETHER_TYPE, type);
|
||||||
|
startService(intent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStartForProvision() {
|
||||||
|
runProvisioningForType(TETHERING_WIFI);
|
||||||
|
|
||||||
|
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
|
||||||
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testScheduleRechecks() {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtra(EXTRA_ADD_TETHER_TYPE, TETHERING_WIFI);
|
||||||
|
intent.putExtra(EXTRA_SET_ALARM, true);
|
||||||
|
startService(intent);
|
||||||
|
|
||||||
|
long period = TEST_CHECK_PERIOD * MS_PER_HOUR;
|
||||||
|
verify(mAlarmManager).setRepeating(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
|
||||||
|
eq(period), mPiCaptor.capture());
|
||||||
|
PendingIntent pi = mPiCaptor.getValue();
|
||||||
|
assertEquals(TetherService.class.getName(), pi.getIntent().getComponent().getClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testStartMultiple() {
|
||||||
|
runProvisioningForType(TETHERING_WIFI);
|
||||||
|
|
||||||
|
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
|
||||||
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
||||||
|
|
||||||
|
runProvisioningForType(TETHERING_USB);
|
||||||
|
|
||||||
|
assertTrue(waitForProvisionRequest(TETHERING_USB));
|
||||||
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
||||||
|
|
||||||
|
runProvisioningForType(TETHERING_BLUETOOTH);
|
||||||
|
|
||||||
|
assertTrue(waitForProvisionRequest(TETHERING_BLUETOOTH));
|
||||||
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testPersistTypes() {
|
||||||
|
runProvisioningForType(TETHERING_WIFI);
|
||||||
|
|
||||||
|
waitForProvisionRequest(TETHERING_WIFI);
|
||||||
|
waitForProvisionResponse(TETHER_ERROR_NO_ERROR);
|
||||||
|
|
||||||
|
runProvisioningForType(TETHERING_BLUETOOTH);
|
||||||
|
|
||||||
|
waitForProvisionRequest(TETHERING_BLUETOOTH);
|
||||||
|
waitForProvisionResponse(TETHER_ERROR_NO_ERROR);
|
||||||
|
|
||||||
|
shutdownService();
|
||||||
|
assertEquals(TETHERING_WIFI + "," + TETHERING_BLUETOOTH, mStoredTypes.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFailureStopsTethering_Wifi() {
|
||||||
|
mProvisionResponse = Activity.RESULT_CANCELED;
|
||||||
|
|
||||||
|
runProvisioningForType(TETHERING_WIFI);
|
||||||
|
|
||||||
|
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
|
||||||
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED));
|
||||||
|
|
||||||
|
verify(mWifiManager).setWifiApEnabled(isNull(WifiConfiguration.class), eq(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testFailureStopsTethering_Usb() {
|
||||||
|
mProvisionResponse = Activity.RESULT_CANCELED;
|
||||||
|
|
||||||
|
runProvisioningForType(TETHERING_USB);
|
||||||
|
|
||||||
|
assertTrue(waitForProvisionRequest(TETHERING_USB));
|
||||||
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_PROVISION_FAILED));
|
||||||
|
|
||||||
|
verify(mConnectivityManager).setUsbTethering(eq(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testCancelAlarm() {
|
||||||
|
runProvisioningForType(TETHERING_WIFI);
|
||||||
|
|
||||||
|
assertTrue(waitForProvisionRequest(TETHERING_WIFI));
|
||||||
|
assertTrue(waitForProvisionResponse(TETHER_ERROR_NO_ERROR));
|
||||||
|
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtra(EXTRA_REM_TETHER_TYPE, TETHERING_WIFI);
|
||||||
|
startService(intent);
|
||||||
|
|
||||||
|
verify(mAlarmManager).cancel(mPiCaptor.capture());
|
||||||
|
PendingIntent pi = mPiCaptor.getValue();
|
||||||
|
assertEquals(TetherService.class.getName(), pi.getIntent().getComponent().getClassName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runProvisioningForType(int type) {
|
||||||
|
Intent intent = new Intent();
|
||||||
|
intent.putExtra(EXTRA_ADD_TETHER_TYPE, type);
|
||||||
|
intent.putExtra(EXTRA_RUN_PROVISION, true);
|
||||||
|
intent.putExtra(EXTRA_PROVISION_CALLBACK, mResultReceiver);
|
||||||
|
startService(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean waitForProvisionRequest(int expectedType) {
|
||||||
|
long startTime = SystemClock.uptimeMillis();
|
||||||
|
while (true) {
|
||||||
|
if (mLastTetherRequestType == expectedType) {
|
||||||
|
mLastTetherRequestType = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((SystemClock.uptimeMillis() - startTime) > PROVISION_TIMEOUT) {
|
||||||
|
Log.v(TAG, String.format(
|
||||||
|
"waitForProvisionRequest timeout: expected=%d, actual=%d",
|
||||||
|
expectedType, mLastTetherRequestType));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SystemClock.sleep(SHORT_TIMEOUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean waitForProvisionResponse(int expectedValue) {
|
||||||
|
long startTime = SystemClock.uptimeMillis();
|
||||||
|
while (true) {
|
||||||
|
if (mLastReceiverResultCode == expectedValue) {
|
||||||
|
mLastReceiverResultCode = BOGUS_RECEIVER_RESULT;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ((SystemClock.uptimeMillis() - startTime) > PROVISION_TIMEOUT) {
|
||||||
|
Log.v(TAG, String.format(
|
||||||
|
"waitForProvisionResponse timeout: expected=%d, actual=%d",
|
||||||
|
expectedValue, mLastReceiverResultCode));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SystemClock.sleep(SHORT_TIMEOUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class MockResources extends android.test.mock.MockResources {
|
||||||
|
@Override
|
||||||
|
public int getInteger(int id) {
|
||||||
|
switch(id) {
|
||||||
|
case com.android.internal.R.integer.config_mobile_hotspot_provision_check_period:
|
||||||
|
return TEST_CHECK_PERIOD;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getString(int id) {
|
||||||
|
switch(id) {
|
||||||
|
case com.android.internal.R.string.config_mobile_hotspot_provision_response:
|
||||||
|
return TEST_RESPONSE_ACTION;
|
||||||
|
case com.android.internal.R.string.config_mobile_hotspot_provision_app_no_ui:
|
||||||
|
return TEST_NO_UI_ACTION;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestContextWrapper extends ContextWrapper {
|
||||||
|
|
||||||
|
public TestContextWrapper(Context base) {
|
||||||
|
super(base);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resources getResources() {
|
||||||
|
return mResources;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SharedPreferences getSharedPreferences(String name, int mode) {
|
||||||
|
// Stub out prefs to control the persisted tether type list.
|
||||||
|
if (name == "tetherPrefs") {
|
||||||
|
return mPrefs;
|
||||||
|
}
|
||||||
|
return super.getSharedPreferences(name, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getSystemService(String name) {
|
||||||
|
if (ALARM_SERVICE.equals(name)) {
|
||||||
|
return mAlarmManager;
|
||||||
|
} else if (CONNECTIVITY_SERVICE.equals(name)) {
|
||||||
|
return mConnectivityManager;
|
||||||
|
} else if (WIFI_SERVICE.equals(name)) {
|
||||||
|
return mWifiManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getSystemService(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class Receiver extends ResultReceiver {
|
||||||
|
final WeakReference<TetherServiceTest> mTest;
|
||||||
|
|
||||||
|
Receiver(TetherServiceTest test) {
|
||||||
|
super(null);
|
||||||
|
mTest = new WeakReference<TetherServiceTest>(test);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||||
|
TetherServiceTest test = mTest.get();
|
||||||
|
if (test != null) {
|
||||||
|
test.mLastReceiverResultCode = resultCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stubs out the provisioning app receiver.
|
||||||
|
*/
|
||||||
|
private class ProvisionReceiver extends BroadcastReceiver {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
mLastTetherRequestType = intent.getIntExtra("TETHER_TYPE", TETHERING_INVALID);
|
||||||
|
sendResponse(mProvisionResponse, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendResponse(int response, Context context) {
|
||||||
|
Intent responseIntent = new Intent(TEST_RESPONSE_ACTION);
|
||||||
|
responseIntent.putExtra(TetherService.EXTRA_RESULT, response);
|
||||||
|
context.sendBroadcast(
|
||||||
|
responseIntent, android.Manifest.permission.CONNECTIVITY_INTERNAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user