blob: 921b59c116214a73836bf52fccd0d0e6e6e56dae [file] [log] [blame]
/*
* Copyright (C) 2017 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.providers.telephony;
import android.content.ContentValues;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ProviderInfo;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.SQLException;
import android.net.Uri;
import android.os.Handler;
import android.provider.Telephony.CarrierId;
import android.telephony.SubscriptionManager;
import android.test.mock.MockContentResolver;
import android.test.mock.MockContext;
import android.util.Log;
import junit.framework.TestCase;
import org.junit.Assert;
import org.junit.Test;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* Tests for testing CRUD operations of CarrierIdProvider.
* Uses CarrierIdProviderTestable to set up in-memory database
*
* Build, install and run the tests by running the commands below:
* runtest --path <dir or file>
* runtest --path <dir or file> --test-method <testMethodName>
* e.g.)
* runtest --path tests/src/com/android/providers/telephony/CarrierIdProviderTest.java \
* --test-method testInsertCarrierInfo
*/
public class CarrierIdProviderTest extends TestCase {
private static final String TAG = CarrierIdProviderTest.class.getSimpleName();
private static final String test_mccmnc = "MCCMNC_TEST";
private static final String test_gid1 = "GID1_TEST";
private static final String test_gid2 = "GID2_TEST";
private static final String test_plmn = "PLMN_TEST";
private static final String test_imsi_prefix = "IMSI_PREFIX_TEST";
private static final String test_spn = "SPN_TEST";
private static final String test_apn = "APN_TEST";
private static final String test_iccid_prefix = "ICCID_PREFIX_TEST";
private static final String test_name = "NAME_TEST";
private static final String test_access_rule =
"B9CFCE1C47A6AC713442718F15EF55B00B3A6D1A6D48CB46249FA8EB51465350";
private static final int test_cid = 0;
private MockContextWithProvider mContext;
private MockContentResolver mContentResolver;
private CarrierIdProviderTestable mCarrierIdProviderTestable;
private FakeContentObserver mContentObserver;
private SharedPreferences mSharedPreferences = mock(SharedPreferences.class);
private SubscriptionManager subscriptionManager = mock(SubscriptionManager.class);
private class FakeContentResolver extends MockContentResolver {
@Override
public void notifyChange(Uri uri, ContentObserver observer) {
super.notifyChange(uri, observer);
Log.d(TAG, "onChanged(uri=" + uri + ")" + observer);
mContentObserver.dispatchChange(false, uri);
}
}
private class FakeContentObserver extends ContentObserver {
private boolean changed = false;
private FakeContentObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
changed = true;
}
}
/**
* This is used to give the CarrierIdProviderTest a mocked context which takes a
* CarrierIdProvider and attaches it to the ContentResolver.
*/
private class MockContextWithProvider extends MockContext {
private final MockContentResolver mResolver;
public MockContextWithProvider(CarrierIdProviderTestable carrierIdProvider) {
mResolver = new FakeContentResolver();
carrierIdProvider.initializeForTesting(this);
Log.d(TAG, "MockContextWithProvider: carrierIdProvider.getContext(): "
+ carrierIdProvider.getContext());
// Add given carrierIdProvider to mResolver, so that mResolver can send queries
// to the provider.
mResolver.addProvider(CarrierIdProvider.AUTHORITY, carrierIdProvider);
Log.d(TAG, "MockContextWithProvider: Add carrierIdProvider to mResolver");
}
@Override
public Object getSystemService(String name) {
switch (name) {
case Context.TELEPHONY_SUBSCRIPTION_SERVICE:
return subscriptionManager;
default:
Log.d(TAG, "getSystemService: returning null");
return null;
}
}
@Override
public MockContentResolver getContentResolver() {
return mResolver;
}
@Override
public int checkCallingOrSelfPermission(String permission) {
return PackageManager.PERMISSION_GRANTED;
}
@Override
public SharedPreferences getSharedPreferences(String name, int mode) {
return mSharedPreferences;
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
mCarrierIdProviderTestable = new CarrierIdProviderTestable();
mContext = new MockContextWithProvider(mCarrierIdProviderTestable);
mContentResolver = mContext.getContentResolver();
mContentObserver = new FakeContentObserver(null);
}
@Override
protected void tearDown() throws Exception {
mCarrierIdProviderTestable.closeDatabase();
super.tearDown();
}
/**
* Test inserting values in carrier identification table.
*/
@Test
public void testInsertCarrierInfo() {
try {
mContentResolver.insert(CarrierId.All.CONTENT_URI, createCarrierInfoInternal());
Cursor countCursor = mContentResolver.query(CarrierId.All.CONTENT_URI,
new String[]{"count(*) AS count"},
null,
null,
null);
countCursor.moveToFirst();
assertEquals(1, countCursor.getInt(0));
assertTrue(mContentObserver.changed);
} catch (Exception e) {
Log.d(TAG, "Error inserting carrier info:" + e);
}
}
/**
* Test invalid insertion of duplicate info
*/
@Test
public void testDuplicateInsertionCarrierInfo() {
try {
//insert same row twice to break uniqueness constraint
ContentValues contentValues = createCarrierInfoInternal();
mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
Assert.fail("should throw an exception for duplicate carrier info");
} catch (Exception e) {
Log.d(TAG, "Error inserting carrier info:" + e);
}
}
/**
* Test invalid insertion of null mccmnc
*/
@Test
public void testInvalidInsertionCarrierInfo() {
try {
//insert a row with null mnccmnc to break not null constraint
ContentValues contentValues = new ContentValues();
contentValues.put(CarrierId.All.GID1, test_gid1);
mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
Assert.fail("should throw an exception for null mccmnc");
} catch (SQLException e) {
Log.d(TAG, "Error inserting carrier info:" + e);
assertFalse(mContentObserver.changed);
}
}
/**
* Test delete.
*/
@Test
public void testDeleteCarrierInfo() {
try {
mContentResolver.insert(CarrierId.All.CONTENT_URI,
createCarrierInfoInternal());
} catch (Exception e) {
Log.d(TAG, "Error inserting carrier info:" + e);
}
int numRowsDeleted = -1;
try {
String whereClause = CarrierId.All.MCCMNC + "=?";
String[] whereArgs = new String[] { test_mccmnc };
numRowsDeleted = mContentResolver.delete(CarrierId.All.CONTENT_URI,
whereClause, whereArgs);
} catch (Exception e) {
Log.d(TAG, "Error deleting values:" + e);
}
assertEquals(1, numRowsDeleted);
assertTrue(mContentObserver.changed);
}
/**
* Test update & query.
*/
@Test
public void testUpdateCarrierInfo() {
int cid = -1;
ContentValues contentValues = createCarrierInfoInternal();
try {
mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
} catch (Exception e) {
Log.d(TAG, "Error inserting carrierInfo:" + e);
}
try {
contentValues.put(CarrierId.CARRIER_ID, 1);
mContentResolver.update(CarrierId.All.CONTENT_URI, contentValues,
CarrierId.All.MCCMNC + "=?", new String[] { test_mccmnc });
} catch (Exception e) {
Log.d(TAG, "Error updating values:" + e);
}
try {
Cursor findEntry = mContentResolver.query(CarrierId.All.CONTENT_URI,
new String[] { CarrierId.CARRIER_ID},
CarrierId.All.MCCMNC + "=?", new String[] { test_mccmnc },
null);
findEntry.moveToFirst();
cid = findEntry.getInt(0);
} catch (Exception e) {
Log.d(TAG, "Query failed:" + e);
}
assertEquals(1, cid);
assertTrue(mContentObserver.changed);
}
@Test
public void testMultiRowInsertionQuery() {
ContentValues contentValues = createCarrierInfoInternal();
try {
// insert a MVNO
mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
// insert its MNO
contentValues = new ContentValues();
contentValues.put(CarrierId.All.MCCMNC, test_mccmnc);
contentValues.put(CarrierId.CARRIER_ID, 1);
mContentResolver.insert(CarrierId.All.CONTENT_URI, contentValues);
} catch (Exception e) {
Log.d(TAG, "Error inserting carrierInfo:" + e);
}
Cursor findEntry = null;
String[] columns = {CarrierId.CARRIER_ID, CarrierId.All.ICCID_PREFIX};
try {
findEntry = mContentResolver.query(CarrierId.All.CONTENT_URI, columns,
CarrierId.All.MCCMNC + "=?", new String[] { test_mccmnc },
null);
} catch (Exception e) {
Log.d(TAG, "Query failed:" + e);
}
assertEquals(2, findEntry.getCount());
try {
// query based on mccmnc & gid1 & iccid_prefix
findEntry = mContentResolver.query(CarrierId.All.CONTENT_URI, columns,
CarrierId.All.MCCMNC + "=? and "
+ CarrierId.All.GID1 + "=? and "
+ CarrierId.All.ICCID_PREFIX + "=?",
new String[] { test_mccmnc, test_gid1, test_iccid_prefix }, null);
} catch (Exception e) {
Log.d(TAG, "Query failed:" + e);
}
assertEquals(1, findEntry.getCount());
findEntry.moveToFirst();
assertEquals(test_cid, findEntry.getInt(0));
assertEquals(test_iccid_prefix, findEntry.getString(1));
}
@Test
public void testGetVersion() {
doReturn(5).when(mSharedPreferences).getInt(eq("version"), anyInt());
int version = 0;
try {
Cursor cursor = mContext.getContentResolver().query(
Uri.withAppendedPath(CarrierId.All.CONTENT_URI,
"get_version"), null, null, null);
cursor.moveToFirst();
version = cursor.getInt(0);
} catch (Exception e) {
Log.d(TAG, "Error querying carrier list version:" + e);
}
assertEquals(5, version);
}
@Test
public void testUpdateCurrentSubscription() {
// update carrier id for subId 1
try {
ContentValues cv = new ContentValues();
cv.put(CarrierId.CARRIER_ID, test_cid);
cv.put(CarrierId.CARRIER_NAME, test_name);
when(subscriptionManager.isActiveSubscriptionId(eq(1))).thenReturn(true);
mContext.getContentResolver().update(Uri.withAppendedPath(CarrierId.CONTENT_URI,
"1"), cv, null, null);
} catch (Exception e) {
Log.d(TAG, "Error updating current subscription: " + e);
e.printStackTrace();
}
int carrierId = -1;
String carrierName = null;
// query carrier id for subId 1
try {
final Cursor c = mContext.getContentResolver().query(
Uri.withAppendedPath(CarrierId.CONTENT_URI, "1"),
new String[] {CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME}, null, null);
c.moveToFirst();
carrierId = c.getInt(0);
carrierName = c.getString(1);
} catch (Exception e) {
Log.d(TAG, "Error query current subscription: " + e);
}
assertEquals(test_cid, carrierId);
assertEquals(test_name, carrierName);
// query carrier id for subId 2
int count = -1;
try {
final Cursor c = mContext.getContentResolver().query(
Uri.withAppendedPath(CarrierId.CONTENT_URI, "2"),
new String[]{CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME}, null, null);
count = c.getCount();
} catch (Exception e) {
Log.d(TAG, "Error query current subscription: " + e);
}
assertEquals(0, count);
// query without subId, expect return carrier id of the default subId
try {
final Cursor c = mContext.getContentResolver().query(CarrierId.CONTENT_URI,
new String[]{CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME}, null, null);
c.moveToFirst();
carrierId = c.getInt(0);
carrierName = c.getString(1);
} catch (Exception e) {
Log.d(TAG, "Error query current subscription: " + e);
}
assertEquals(test_cid, carrierId);
assertEquals(test_name, carrierName);
}
@Test(expected = IllegalArgumentException.class)
public void testQueryCurrrentSubscription_wrongProjection() {
mContext.getContentResolver().query(CarrierId.CONTENT_URI,
new String[]{CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME, CarrierId.All.MCCMNC},
null, null);
}
@Test(expected = IllegalArgumentException.class)
public void testQueryWithWrongURI() {
try {
mContext.getContentResolver().query(Uri.withAppendedPath(
CarrierId.CONTENT_URI, "invalid"),
new String[]{CarrierId.CARRIER_ID, CarrierId.CARRIER_NAME}, null, null);
Assert.fail("should throw an exception for wrong uri");
} catch (IllegalArgumentException ex) {
}
}
@Test(expected = IllegalArgumentException.class)
public void testUpdateCurrentSubscription_WrongURI() {
try {
ContentValues cv = new ContentValues();
cv.put(CarrierId.CARRIER_ID, test_cid);
cv.put(CarrierId.CARRIER_NAME, test_name);
mContext.getContentResolver().update(CarrierId.CONTENT_URI, cv, null, null);
Assert.fail("should throw an exception for wrong uri");
} catch (IllegalArgumentException ex) {
assertFalse(mContentObserver.changed);
}
}
private static ContentValues createCarrierInfoInternal() {
ContentValues contentValues = new ContentValues();
contentValues.put(CarrierId.All.MCCMNC, test_mccmnc);
contentValues.put(CarrierId.All.GID1, test_gid1);
contentValues.put(CarrierId.All.GID2, test_gid2);
contentValues.put(CarrierId.All.PLMN, test_plmn);
contentValues.put(CarrierId.All.IMSI_PREFIX_XPATTERN, test_imsi_prefix);
contentValues.put(CarrierId.All.SPN, test_spn);
contentValues.put(CarrierId.All.APN, test_apn);
contentValues.put(CarrierId.All.ICCID_PREFIX, test_iccid_prefix);
contentValues.put(CarrierId.CARRIER_NAME, test_name);
contentValues.put(CarrierId.CARRIER_ID, test_cid);
contentValues.put(CarrierId.All.PRIVILEGE_ACCESS_RULE, test_access_rule);
return contentValues;
}
}