The mainly changed:
1. Will not insert invalid apn data to database.
2. Clicking back button will save the APN data to database if the data is valid.
Test: make ROBOTEST_FILTER=ApnEditorTest -j40 RunSettingsRoboTests
Bug: 73745458
Bug: 67327863
Merged-In: Ie2c147cae03ad78d43c351e05add761b2dffac0c
Change-Id: Ie2c147cae03ad78d43c351e05add761b2dffac0c
(cherry picked from commit f39ef85653)
463 lines
18 KiB
Java
463 lines
18 KiB
Java
/*
|
|
* Copyright (C) 2018 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 com.google.common.truth.Truth.assertThat;
|
|
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.Mockito.doNothing;
|
|
import static org.mockito.Mockito.doReturn;
|
|
import static org.mockito.Mockito.spy;
|
|
import static org.mockito.Mockito.verify;
|
|
|
|
import android.app.Activity;
|
|
import android.content.ContentResolver;
|
|
import android.content.ContentValues;
|
|
import android.content.Context;
|
|
import android.content.res.Resources;
|
|
import android.database.Cursor;
|
|
import android.net.Uri;
|
|
import android.support.v14.preference.MultiSelectListPreference;
|
|
import android.support.v14.preference.SwitchPreference;
|
|
import android.support.v7.preference.EditTextPreference;
|
|
import android.support.v7.preference.ListPreference;
|
|
import android.view.KeyEvent;
|
|
import android.view.Menu;
|
|
import android.view.MenuItem;
|
|
import android.view.View;
|
|
|
|
import com.android.settings.ApnEditor.ApnData;
|
|
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
|
|
|
import org.junit.Before;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.mockito.ArgumentCaptor;
|
|
import org.mockito.Captor;
|
|
import org.mockito.Mock;
|
|
import org.mockito.Mockito;
|
|
import org.mockito.MockitoAnnotations;
|
|
import org.robolectric.Robolectric;
|
|
import org.robolectric.RuntimeEnvironment;
|
|
|
|
@RunWith(SettingsRobolectricTestRunner.class)
|
|
public class ApnEditorTest {
|
|
|
|
private static final Object[] APN_DATA = new Object[] {
|
|
0, /* ID */
|
|
"apn_name" /* apn name */,
|
|
"apn.com" /* apn */,
|
|
"" /* proxy */,
|
|
"" /* port */,
|
|
"" /* username */,
|
|
"" /* server */,
|
|
"" /* password */,
|
|
"" /* MMSC */,
|
|
"123" /* MCC */,
|
|
"456" /* MNC */,
|
|
"123456" /* operator numeric */,
|
|
"" /* MMS proxy */,
|
|
"" /* MMS port */,
|
|
0 /* Authentication type */,
|
|
"default,supl,ia" /* APN type */,
|
|
"IPv6" /* APN protocol */,
|
|
1 /* APN enable/disable */,
|
|
0 /* Bearer */,
|
|
0 /* Bearer BITMASK*/,
|
|
"IPv4" /* APN roaming protocol */,
|
|
"None" /* MVNO type */,
|
|
"", /* MVNO value */
|
|
};
|
|
|
|
private static final int CURSOR_INTEGER_INDEX = 0;
|
|
private static final int CURSOR_STRING_INDEX = 1;
|
|
|
|
private static final Uri mApnUri = Uri.parse("Apn://row/1");
|
|
|
|
@Mock
|
|
private Cursor mCursor;
|
|
|
|
@Captor
|
|
private ArgumentCaptor<Uri> mUriCaptor;
|
|
|
|
private ApnEditor mApnEditorUT;
|
|
private Activity mActivity;
|
|
private Resources mResources;
|
|
|
|
@Before
|
|
public void setUp() {
|
|
MockitoAnnotations.initMocks(this);
|
|
mActivity = spy(Robolectric.setupActivity(Activity.class));
|
|
mResources = mActivity.getResources();
|
|
mApnEditorUT = spy(new ApnEditor());
|
|
|
|
doReturn(mActivity).when(mApnEditorUT).getActivity();
|
|
doReturn(mResources).when(mApnEditorUT).getResources();
|
|
doNothing().when(mApnEditorUT).finish();
|
|
doNothing().when(mApnEditorUT).showError();
|
|
|
|
setMockPreference(mActivity);
|
|
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
|
|
mApnEditorUT.sNotSet = "Not Set";
|
|
}
|
|
|
|
@Test
|
|
public void testSetStringValue_valueChanged_shouldSetValue() {
|
|
// GIVEN an APN value which is different than the APN value in database
|
|
final String apnKey = "apn";
|
|
final String apnValue = "testing.com";
|
|
final ContentValues cv = new ContentValues();
|
|
|
|
// WHEN try to check and set the apn value
|
|
final boolean isDiff = mApnEditorUT.setStringValueAndCheckIfDiff(
|
|
cv, apnKey, apnValue, false /* assumeDiff */, ApnEditor.APN_INDEX);
|
|
|
|
// THEN the APN value is different than the one in database, and it has been stored in the
|
|
// given ContentValues
|
|
assertThat(isDiff).isTrue();
|
|
assertThat(apnValue).isEqualTo(cv.getAsString(apnKey));
|
|
}
|
|
|
|
@Test
|
|
public void testSetStringValue_valueNotChanged_shouldNotSetValue() {
|
|
// GIVEN an APN value which is same as the APN value in database
|
|
final String apnKey = "apn";
|
|
final String apnValue = (String) APN_DATA[ApnEditor.APN_INDEX];
|
|
final ContentValues cv = new ContentValues();
|
|
|
|
// WHEN try to check and set the apn value
|
|
final boolean isDiff = mApnEditorUT.setStringValueAndCheckIfDiff(
|
|
cv, apnKey, apnValue, false /* assumeDiff */, ApnEditor.APN_INDEX);
|
|
|
|
// THEN the APN value is same as the one in database, and the new APN value is not stored
|
|
// in the given ContentValues
|
|
assertThat(isDiff).isFalse();
|
|
assertThat(cv.get(apnKey)).isNull();
|
|
}
|
|
|
|
@Test
|
|
public void testSetStringValue_nullValue_shouldNotSetValue_shouldNotSetValue() {
|
|
// GIVEN a null APN value
|
|
final String apnKey = "apn";
|
|
final String apnValue = null;
|
|
final ContentValues cv = new ContentValues();
|
|
|
|
// WHEN try to check and set the apn value
|
|
final boolean isDiff = mApnEditorUT.setStringValueAndCheckIfDiff(
|
|
cv, apnKey, apnValue, false /* assumeDiff */, ApnEditor.APN_INDEX);
|
|
|
|
// THEN the APN value is different than the one in database, but the null value is not
|
|
// stored in the given ContentValues
|
|
assertThat(isDiff).isTrue();
|
|
assertThat(cv.get(apnKey)).isNull();
|
|
}
|
|
|
|
@Test
|
|
public void testSetIntValue_valueChanged_shouldSetValue() {
|
|
// GIVEN a value indicated whether the apn is enabled, and it's different than the value in
|
|
// the database
|
|
final String apnEnabledKey = "apn_enabled";
|
|
final int apnEnabledValue = 0;
|
|
final ContentValues cv = new ContentValues();
|
|
|
|
// WHEN try to check and set the apn enabled
|
|
final boolean isDiff = mApnEditorUT.setIntValueAndCheckIfDiff(
|
|
cv,
|
|
apnEnabledKey,
|
|
apnEnabledValue,
|
|
false /* assumeDiff */,
|
|
ApnEditor.CARRIER_ENABLED_INDEX);
|
|
|
|
// THEN the apn enabled field is different than the one in database, and it has been stored
|
|
// in the given ContentValues
|
|
assertThat(isDiff).isTrue();
|
|
assertThat(cv.getAsInteger(apnEnabledKey)).isEqualTo(apnEnabledValue);
|
|
}
|
|
|
|
@Test
|
|
public void testSetIntValue_valueNotChanged_shouldNotSetValue() {
|
|
// GIVEN a value indicated whether the apn is enabled, and it's same as the one in the
|
|
// database
|
|
final String apnEnabledKey = "apn_enabled";
|
|
final int apnEnabledValue = (int) APN_DATA[ApnEditor.CARRIER_ENABLED_INDEX];
|
|
final ContentValues cv = new ContentValues();
|
|
|
|
// WHEN try to check and set the apn enabled
|
|
final boolean isDiff = mApnEditorUT.setIntValueAndCheckIfDiff(
|
|
cv,
|
|
apnEnabledKey,
|
|
apnEnabledValue,
|
|
false /* assumeDiff */,
|
|
ApnEditor.CARRIER_ENABLED_INDEX);
|
|
|
|
// THEN the apn enabled field is same as the one in the database, and the filed is not
|
|
// stored in the given ContentValues
|
|
assertThat(isDiff).isFalse();
|
|
assertThat(cv.get(apnEnabledKey)).isNull();
|
|
}
|
|
|
|
@Test
|
|
public void testValidateApnData_validData_shouldReturnNull() {
|
|
// GIVEN a valid apn data
|
|
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
|
|
mApnEditorUT.fillUI(true /* firstTime */);
|
|
|
|
// WHEN validate the apn data
|
|
final String errMsg = mApnEditorUT.validateApnData();
|
|
|
|
// THEN the error message should be null
|
|
assertThat(errMsg).isNull();
|
|
}
|
|
|
|
@Test
|
|
public void testValidateApn_apnNameNotSet_shouldReturnErrorMessage() {
|
|
// GIVEN a apn data without the apn name
|
|
final FakeApnData apnData = new FakeApnData(APN_DATA);
|
|
apnData.mData[ApnEditor.NAME_INDEX] = "";
|
|
mApnEditorUT.mApnData = apnData;
|
|
mApnEditorUT.fillUI(true /* firstTime */);
|
|
|
|
// THEN validate the apn data
|
|
final String errMsg = mApnEditorUT.validateApnData();
|
|
|
|
// THEN the error message indicated the apn name not set is returned
|
|
assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_name_empty));
|
|
}
|
|
|
|
@Test
|
|
public void testValidateApnData_apnNotSet_shouldReturnErrorMessage() {
|
|
// GIVEN a apn data without the apn
|
|
final FakeApnData apnData = new FakeApnData(APN_DATA);
|
|
apnData.mData[ApnEditor.APN_INDEX] = "";
|
|
mApnEditorUT.mApnData = apnData;
|
|
mApnEditorUT.fillUI(true /* firstTime */);
|
|
|
|
// THEN validate the apn data
|
|
final String errMsg = mApnEditorUT.validateApnData();
|
|
|
|
// THEN the error message indicated the apn not set is returned
|
|
assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_apn_empty));
|
|
}
|
|
|
|
@Test
|
|
public void testValidateApnData_mccInvalid_shouldReturnErrorMessage() {
|
|
// GIVEN a apn data with invalid mcc
|
|
final FakeApnData apnData = new FakeApnData(APN_DATA);
|
|
// The length of the mcc should be 3
|
|
apnData.mData[ApnEditor.MCC_INDEX] = "1324";
|
|
mApnEditorUT.mApnData = apnData;
|
|
mApnEditorUT.fillUI(true /* firstTime */);
|
|
|
|
// WHEN validate the apn data
|
|
final String errMsg = mApnEditorUT.validateApnData();
|
|
|
|
// THEN the error message indicated the mcc invalid is returned
|
|
assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_mcc_not3));
|
|
}
|
|
|
|
@Test
|
|
public void testValidateApnData_mncInvalid_shouldReturnErrorMessage() {
|
|
// GIVEN an apn data with invalid mnc
|
|
final FakeApnData apnData = new FakeApnData(APN_DATA);
|
|
// The length of the mnc should be 2 or 3
|
|
apnData.mData[ApnEditor.MNC_INDEX] = "1324";
|
|
mApnEditorUT.mApnData = apnData;
|
|
mApnEditorUT.fillUI(true /* firstTime */);
|
|
|
|
// WHEN validate the apn data
|
|
final String errMsg = mApnEditorUT.validateApnData();
|
|
|
|
// THEN the error message indicated the mnc invalid is returned
|
|
assertThat(errMsg).isEqualTo(mResources.getString(R.string.error_mnc_not23));
|
|
}
|
|
|
|
@Test
|
|
public void testSaveApnData_pressBackButtonWithValidApnData_shouldSaveApnData() {
|
|
// GIVEN a valid apn data
|
|
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
|
|
mApnEditorUT.fillUI(true /* firstTime */);
|
|
|
|
// WHEN press the back button
|
|
final KeyEvent event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
|
|
mApnEditorUT.onKey(new View(mActivity), KeyEvent.KEYCODE_BACK, event);
|
|
|
|
// THEN the apn data is saved and the apn editor is closed
|
|
verify(mApnEditorUT).validateAndSaveApnData();
|
|
verify(mApnEditorUT).finish();
|
|
}
|
|
|
|
@Test
|
|
public void testSaveApnData_pressSaveButtonWithValidApnData_shouldSaveApnData() {
|
|
// GIVEN a valid apn data
|
|
mApnEditorUT.mApnData = new FakeApnData(APN_DATA);
|
|
mApnEditorUT.fillUI(true /* firstTime */);
|
|
|
|
// WHEN press the save button
|
|
MenuItem item = Mockito.mock(MenuItem.class);
|
|
// Menu.FIRST + 1 indicated the SAVE option in ApnEditor
|
|
doReturn(Menu.FIRST + 1).when(item).getItemId();
|
|
mApnEditorUT.onOptionsItemSelected(item);
|
|
|
|
// THEN the apn data is saved and the apn editor is closed
|
|
verify(mApnEditorUT).validateAndSaveApnData();
|
|
verify(mApnEditorUT).finish();
|
|
}
|
|
|
|
@Test
|
|
public void testSaveApnData_apnDataInvalid_shouldNotSaveApnData() {
|
|
// GIVEN an invalid apn data
|
|
final FakeApnData apnData = new FakeApnData(APN_DATA);
|
|
// The valid apn data should contains a non-empty apn name
|
|
apnData.mData[ApnEditor.NAME_INDEX] = "";
|
|
mApnEditorUT.mApnData = apnData;
|
|
mApnEditorUT.fillUI(true /* firstTime */);
|
|
|
|
// WHEN press the save button
|
|
final MenuItem item = Mockito.mock(MenuItem.class);
|
|
// Menu.FIRST + 1 indicated the SAVE option in ApnEditor
|
|
doReturn(Menu.FIRST + 1).when(item).getItemId();
|
|
mApnEditorUT.onOptionsItemSelected(item);
|
|
|
|
// THEN the error dialog is shown
|
|
verify(mApnEditorUT).validateAndSaveApnData();
|
|
verify(mApnEditorUT).showError();
|
|
}
|
|
|
|
@Test
|
|
public void testDeleteApnData_shouldDeleteData() {
|
|
// GIVEN a valid apn data correspond a row in database
|
|
final Uri apnUri = Uri.parse("content://telephony/carriers/1");
|
|
mApnEditorUT.mApnData = new FakeApnData(APN_DATA, apnUri);
|
|
mApnEditorUT.fillUI(true /* firstTime */);
|
|
ContentResolver mockContentResolver = Mockito.mock(ContentResolver.class);
|
|
doReturn(mockContentResolver).when(mActivity).getContentResolver();
|
|
|
|
// WHEN press the save button
|
|
final MenuItem item = Mockito.mock(MenuItem.class);
|
|
// Menu.FIRST indicated the DELETE option in ApnEditor
|
|
doReturn(Menu.FIRST).when(item).getItemId();
|
|
mApnEditorUT.onOptionsItemSelected(item);
|
|
|
|
// THEN the apn data is deleted and the apn editor is closed
|
|
verify(mockContentResolver).delete(mUriCaptor.capture(), any(), any());
|
|
assertThat(apnUri).isEqualTo(mUriCaptor.getValue());
|
|
verify(mApnEditorUT).finish();
|
|
}
|
|
|
|
@Test(expected = ClassCastException.class)
|
|
public void testApnData_invalidIntegerType_throwsInvalidTypeException() {
|
|
// GIVEN a ApnData constructed from cursor
|
|
initCursor();
|
|
final ApnData data = new ApnData(mApnUri, mCursor);
|
|
|
|
// WHEN get a string from an integer column
|
|
// THEN the InvalidTypeException is threw
|
|
data.getString(CURSOR_INTEGER_INDEX);
|
|
}
|
|
|
|
@Test(expected = ClassCastException.class)
|
|
public void testApnData_invalidStringType_throwsInvalidTypeException() {
|
|
// GIVEN a ApnData constructed from cursor
|
|
initCursor();
|
|
final ApnData data = new ApnData(mApnUri, mCursor);
|
|
|
|
// WHEN get a integer from a string column
|
|
// THEN the InvalidTypeException is threw
|
|
data.getInteger(CURSOR_STRING_INDEX);
|
|
}
|
|
|
|
@Test
|
|
public void testApnData_validIntegerType_returnCorrectValue() {
|
|
// GIVEN a ApnData constructed from cursor
|
|
initCursor();
|
|
final ApnData data = new ApnData(mApnUri, mCursor);
|
|
|
|
// WHEN get integer from an integer column
|
|
final int val = data.getInteger(CURSOR_INTEGER_INDEX);
|
|
|
|
// THEN the integer is returned correctly
|
|
assertThat(val).isEqualTo(mCursor.getInt(CURSOR_INTEGER_INDEX));
|
|
}
|
|
|
|
@Test
|
|
public void testApnData_validStringType_returnCorrectValue() {
|
|
// GIVEN a ApnData constructed from cursor
|
|
initCursor();
|
|
final ApnData data = new ApnData(mApnUri, mCursor);
|
|
|
|
// WHEN get string from a string column
|
|
final String str = data.getString(CURSOR_STRING_INDEX);
|
|
|
|
// THEN the integer is returned correctly
|
|
assertThat(str).isEqualTo(mCursor.getString(CURSOR_STRING_INDEX));
|
|
}
|
|
|
|
@Test
|
|
public void testApnData_nullValueColumn_returnNull() {
|
|
// GIVEN a empty ApnData
|
|
final ApnData data = new ApnData(3);
|
|
|
|
// WHEN get string value from a null column
|
|
final String str = data.getString(0);
|
|
|
|
// THEN the null value is returned
|
|
assertThat(str).isNull();
|
|
}
|
|
|
|
private void initCursor() {
|
|
doReturn(2).when(mCursor).getColumnCount();
|
|
doReturn(Integer.valueOf(2)).when(mCursor).getInt(CURSOR_INTEGER_INDEX);
|
|
doReturn("str").when(mCursor).getString(CURSOR_STRING_INDEX);
|
|
doReturn(Cursor.FIELD_TYPE_INTEGER).when(mCursor).getType(CURSOR_INTEGER_INDEX);
|
|
doReturn(Cursor.FIELD_TYPE_STRING).when(mCursor).getType(CURSOR_STRING_INDEX);
|
|
}
|
|
|
|
private void setMockPreference(Context context) {
|
|
mApnEditorUT.mName = new EditTextPreference(context);
|
|
mApnEditorUT.mApn = new EditTextPreference(context);
|
|
mApnEditorUT.mProxy = new EditTextPreference(context);
|
|
mApnEditorUT.mPort = new EditTextPreference(context);
|
|
mApnEditorUT.mUser = new EditTextPreference(context);
|
|
mApnEditorUT.mServer = new EditTextPreference(context);
|
|
mApnEditorUT.mPassword = new EditTextPreference(context);
|
|
mApnEditorUT.mMmsc = new EditTextPreference(context);
|
|
mApnEditorUT.mMcc = new EditTextPreference(context);
|
|
mApnEditorUT.mMnc = new EditTextPreference(context);
|
|
mApnEditorUT.mMmsProxy = new EditTextPreference(context);
|
|
mApnEditorUT.mMmsPort = new EditTextPreference(context);
|
|
mApnEditorUT.mAuthType = new ListPreference(context);
|
|
mApnEditorUT.mApnType = new EditTextPreference(context);
|
|
mApnEditorUT.mProtocol = new ListPreference(context);
|
|
mApnEditorUT.mRoamingProtocol = new ListPreference(context);
|
|
mApnEditorUT.mCarrierEnabled = new SwitchPreference(context);
|
|
mApnEditorUT.mBearerMulti = new MultiSelectListPreference(context);
|
|
mApnEditorUT.mMvnoType = new ListPreference(context);
|
|
mApnEditorUT.mMvnoMatchData = new EditTextPreference(context);
|
|
}
|
|
|
|
private final class FakeApnData extends ApnData {
|
|
FakeApnData(Object[] data) {
|
|
super(data.length);
|
|
System.arraycopy(data, 0, mData, 0, data.length);
|
|
}
|
|
|
|
FakeApnData(Object[] data, Uri uri) {
|
|
this(data);
|
|
mUri = uri;
|
|
}
|
|
}
|
|
} |