diff options
| author | Chen Xu <fionaxu@google.com> | 2020-06-24 22:21:59 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2020-06-24 22:21:59 +0000 |
| commit | 198f29e82b96bd79ad974ddf0ef0200d00a334f9 (patch) | |
| tree | a511acf1111cfcd00d4b0f44ad99509c3df4187f | |
| parent | 2a0ac1a43f91a148e66866fe144d211992b8d025 (diff) | |
| parent | 643973c43986c7771ad18233d20206f7fa60aacb (diff) | |
| download | platform_packages_apps_CellBroadcastReceiver-198f29e82b96bd79ad974ddf0ef0200d00a334f9.tar.gz platform_packages_apps_CellBroadcastReceiver-198f29e82b96bd79ad974ddf0ef0200d00a334f9.tar.bz2 platform_packages_apps_CellBroadcastReceiver-198f29e82b96bd79ad974ddf0ef0200d00a334f9.zip | |
Merge "improve test coverage for cellbroadcastcontentprovider" into rvc-dev
5 files changed, 349 insertions, 27 deletions
diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastContentProvider.java b/src/com/android/cellbroadcastreceiver/CellBroadcastContentProvider.java index 4f7572d6b..6c93104af 100644 --- a/src/com/android/cellbroadcastreceiver/CellBroadcastContentProvider.java +++ b/src/com/android/cellbroadcastreceiver/CellBroadcastContentProvider.java @@ -34,6 +34,7 @@ import android.telephony.SmsCbLocation; import android.telephony.SmsCbMessage; import android.text.TextUtils; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; /** * ContentProvider for the database of received cell broadcasts. @@ -68,7 +69,8 @@ public class CellBroadcastContentProvider extends ContentProvider { } /** The database for this content provider. */ - private SQLiteOpenHelper mOpenHelper; + @VisibleForTesting + public SQLiteOpenHelper mOpenHelper; /** * Initialize content provider. @@ -232,7 +234,8 @@ public class CellBroadcastContentProvider extends ContentProvider { * @param message the message to insert * @return true if the broadcast is new, false if it's a duplicate broadcast. */ - boolean insertNewBroadcast(SmsCbMessage message) { + @VisibleForTesting + public boolean insertNewBroadcast(SmsCbMessage message) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); ContentValues cv = getContentValues(message); @@ -257,7 +260,8 @@ public class CellBroadcastContentProvider extends ContentProvider { * @param rowId the row ID of the broadcast to delete * @return true if the database was updated, false otherwise */ - boolean deleteBroadcast(long rowId) { + @VisibleForTesting + public boolean deleteBroadcast(long rowId) { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int rowCount = db.delete(CellBroadcastDatabaseHelper.TABLE_NAME, @@ -275,7 +279,8 @@ public class CellBroadcastContentProvider extends ContentProvider { * Internal method to delete all cell broadcasts and notify observers. * @return true if the database was updated, false otherwise */ - boolean deleteAllBroadcasts() { + @VisibleForTesting + public boolean deleteAllBroadcasts() { SQLiteDatabase db = mOpenHelper.getWritableDatabase(); int rowCount = db.delete(CellBroadcastDatabaseHelper.TABLE_NAME, null, null); diff --git a/src/com/android/cellbroadcastreceiver/CellBroadcastDatabaseHelper.java b/src/com/android/cellbroadcastreceiver/CellBroadcastDatabaseHelper.java index fd736f330..ff264d3a2 100644 --- a/src/com/android/cellbroadcastreceiver/CellBroadcastDatabaseHelper.java +++ b/src/com/android/cellbroadcastreceiver/CellBroadcastDatabaseHelper.java @@ -25,7 +25,9 @@ import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import android.os.RemoteException; import android.provider.Telephony; +import android.provider.Telephony.CellBroadcasts; import android.util.Log; +import com.android.internal.annotations.VisibleForTesting; /** * Open, create, and upgrade the cell broadcast SQLite database. Previously an inner class of @@ -38,7 +40,8 @@ public class CellBroadcastDatabaseHelper extends SQLiteOpenHelper { private static final String TAG = "CellBroadcastDatabaseHelper"; private static final String DATABASE_NAME = "cell_broadcasts.db"; - static final String TABLE_NAME = "broadcasts"; + @VisibleForTesting + public static final String TABLE_NAME = "broadcasts"; /* * Query columns for instantiating SmsCbMessage. @@ -68,6 +71,37 @@ public class CellBroadcastDatabaseHelper extends SQLiteOpenHelper { }; /** + * Returns a string used to create the cell broadcast table. This is exposed so the unit test + * can construct its own in-memory database to match the cell broadcast db. + */ + @VisibleForTesting + public static String getStringForCellBroadcastTableCreation(String tableName) { + return "CREATE TABLE " + tableName + " (" + + CellBroadcasts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + + CellBroadcasts.SLOT_INDEX + " INTEGER DEFAULT 0," + + CellBroadcasts.GEOGRAPHICAL_SCOPE + " INTEGER," + + CellBroadcasts.PLMN + " TEXT," + + CellBroadcasts.LAC + " INTEGER," + + CellBroadcasts.CID + " INTEGER," + + CellBroadcasts.SERIAL_NUMBER + " INTEGER," + + Telephony.CellBroadcasts.SERVICE_CATEGORY + " INTEGER," + + Telephony.CellBroadcasts.LANGUAGE_CODE + " TEXT," + + Telephony.CellBroadcasts.MESSAGE_BODY + " TEXT," + + Telephony.CellBroadcasts.DELIVERY_TIME + " INTEGER," + + Telephony.CellBroadcasts.MESSAGE_READ + " INTEGER," + + Telephony.CellBroadcasts.MESSAGE_FORMAT + " INTEGER," + + Telephony.CellBroadcasts.MESSAGE_PRIORITY + " INTEGER," + + Telephony.CellBroadcasts.ETWS_WARNING_TYPE + " INTEGER," + + Telephony.CellBroadcasts.CMAS_MESSAGE_CLASS + " INTEGER," + + Telephony.CellBroadcasts.CMAS_CATEGORY + " INTEGER," + + Telephony.CellBroadcasts.CMAS_RESPONSE_TYPE + " INTEGER," + + Telephony.CellBroadcasts.CMAS_SEVERITY + " INTEGER," + + Telephony.CellBroadcasts.CMAS_URGENCY + " INTEGER," + + Telephony.CellBroadcasts.CMAS_CERTAINTY + " INTEGER);"; + } + + + /** * Database version 1: initial version (support removed) * Database version 2-9: (reserved for OEM database customization) (support removed) * Database version 10: adds ETWS and CMAS columns and CDMA support (support removed) @@ -87,28 +121,7 @@ public class CellBroadcastDatabaseHelper extends SQLiteOpenHelper { @Override public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + TABLE_NAME + " (" - + Telephony.CellBroadcasts._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," - + Telephony.CellBroadcasts.SLOT_INDEX + " INTEGER DEFAULT 0," - + Telephony.CellBroadcasts.GEOGRAPHICAL_SCOPE + " INTEGER," - + Telephony.CellBroadcasts.PLMN + " TEXT," - + Telephony.CellBroadcasts.LAC + " INTEGER," - + Telephony.CellBroadcasts.CID + " INTEGER," - + Telephony.CellBroadcasts.SERIAL_NUMBER + " INTEGER," - + Telephony.CellBroadcasts.SERVICE_CATEGORY + " INTEGER," - + Telephony.CellBroadcasts.LANGUAGE_CODE + " TEXT," - + Telephony.CellBroadcasts.MESSAGE_BODY + " TEXT," - + Telephony.CellBroadcasts.DELIVERY_TIME + " INTEGER," - + Telephony.CellBroadcasts.MESSAGE_READ + " INTEGER," - + Telephony.CellBroadcasts.MESSAGE_FORMAT + " INTEGER," - + Telephony.CellBroadcasts.MESSAGE_PRIORITY + " INTEGER," - + Telephony.CellBroadcasts.ETWS_WARNING_TYPE + " INTEGER," - + Telephony.CellBroadcasts.CMAS_MESSAGE_CLASS + " INTEGER," - + Telephony.CellBroadcasts.CMAS_CATEGORY + " INTEGER," - + Telephony.CellBroadcasts.CMAS_RESPONSE_TYPE + " INTEGER," - + Telephony.CellBroadcasts.CMAS_SEVERITY + " INTEGER," - + Telephony.CellBroadcasts.CMAS_URGENCY + " INTEGER," - + Telephony.CellBroadcasts.CMAS_CERTAINTY + " INTEGER);"); + db.execSQL(getStringForCellBroadcastTableCreation(TABLE_NAME)); db.execSQL("CREATE INDEX IF NOT EXISTS deliveryTimeIndex ON " + TABLE_NAME + " (" + Telephony.CellBroadcasts.DELIVERY_TIME + ");"); diff --git a/tests/unit/Android.bp b/tests/unit/Android.bp index 66bffd791..4b8d067c0 100644 --- a/tests/unit/Android.bp +++ b/tests/unit/Android.bp @@ -18,6 +18,7 @@ java_defaults { "android.test.runner", "telephony-common", "android.test.base", + "android.test.mock", ], static_libs: [ "androidx.test.rules", diff --git a/tests/unit/src/com/android/cellbroadcastreceiver/unit/CellBroadcastContentProviderTest.java b/tests/unit/src/com/android/cellbroadcastreceiver/unit/CellBroadcastContentProviderTest.java new file mode 100644 index 000000000..6b0cffe15 --- /dev/null +++ b/tests/unit/src/com/android/cellbroadcastreceiver/unit/CellBroadcastContentProviderTest.java @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2020 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.cellbroadcastreceiver.unit; + +import static org.mockito.Mockito.doReturn; +import static com.google.common.truth.Truth.assertThat; + +import android.content.ContentValues; +import android.content.pm.PackageManager; +import android.database.Cursor; +import android.net.Uri; +import android.provider.Telephony.CellBroadcasts; +import android.telephony.SmsCbCmasInfo; +import android.telephony.SmsCbEtwsInfo; +import android.telephony.SmsCbLocation; +import android.telephony.SmsCbMessage; +import android.test.mock.MockContentResolver; +import android.test.mock.MockContext; +import android.util.Log; +import com.android.cellbroadcastreceiver.CellBroadcastDatabaseHelper; +import junit.framework.TestCase; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +public class CellBroadcastContentProviderTest extends TestCase { + private static final String TAG = CellBroadcastContentProviderTest.class.getSimpleName(); + + public static final Uri CONTENT_URI = Uri.parse("content://cellbroadcasts-app"); + + private static final int GEO_SCOPE = 1; + private static final String PLMN = "123456"; + private static final int LAC = 13; + private static final int CID = 123; + private static final int SERIAL_NUMBER = 17984; + private static final int SERVICE_CATEGORY = 4379; + private static final String LANGUAGE_CODE = "en"; + private static final String MESSAGE_BODY = "AMBER Alert: xxxx"; + private static final int MESSAGE_FORMAT = 1; + private static final int MESSAGE_PRIORITY = 3; + private static final int ETWS_WARNING_TYPE = 1; + private static final int CMAS_MESSAGE_CLASS = 1; + private static final int CMAS_CATEGORY = 6; + private static final int CMAS_RESPONSE_TYPE = 1; + private static final int CMAS_SEVERITY = 2; + private static final int CMAS_URGENCY = 3; + private static final int CMAS_CERTAINTY = 4; + + private CellBroadcastContentProviderTestable mCellBroadcastProviderTestable; + private MockContextWithProvider mContext; + private MockContentResolver mContentResolver; + + @Override + protected void setUp() throws Exception { + super.setUp(); + MockitoAnnotations.initMocks(this); + + mCellBroadcastProviderTestable = new CellBroadcastContentProviderTestable(); + mContext = new MockContextWithProvider(mCellBroadcastProviderTestable); + mContentResolver = mContext.getContentResolver(); + } + + @Override + protected void tearDown() throws Exception { + mCellBroadcastProviderTestable.closeDatabase(); + super.tearDown(); + } + + @Test + public void testInsert() { + try { + ContentValues msg = new ContentValues(); + msg.put(CellBroadcasts.SERIAL_NUMBER, SERIAL_NUMBER); + mContentResolver.insert(CONTENT_URI, msg); + fail(); + } catch (UnsupportedOperationException ex) { + // pass the test + } + } + + @Test + public void testDelete() { + try { + mContentResolver.delete(CONTENT_URI, null, null); + fail(); + } catch (UnsupportedOperationException ex) { + // pass the test + } + } + + @Test + public void testUpdate() { + try { + mContentResolver.update(CONTENT_URI, null, null); + fail(); + } catch (UnsupportedOperationException ex) { + // pass the test + } + } + + @Test + public void testDeleteAll() { + // Insert a cell broadcast message + mCellBroadcastProviderTestable.insertNewBroadcast(fakeSmsCbMessage()); + // Verify that the record is inserted into the database correctly. + Cursor cursor = mContentResolver.query(CONTENT_URI, + CellBroadcastDatabaseHelper.QUERY_COLUMNS, null, null, null); + assertThat(cursor.getCount()).isEqualTo(1); + // delete all + mCellBroadcastProviderTestable.deleteAllBroadcasts(); + cursor = mContentResolver.query(CONTENT_URI, CellBroadcastDatabaseHelper.QUERY_COLUMNS, + null, null, null); + assertThat(cursor.getCount()).isEqualTo(0); + } + + @Test + public void testDeleteBroadcast() { + // Insert two cell broadcast message + mCellBroadcastProviderTestable.insertNewBroadcast(fakeSmsCbMessage()); + mCellBroadcastProviderTestable.insertNewBroadcast(fakeSmsCbMessage()); + // Verify that the record is inserted into the database correctly. + Cursor cursor = mContentResolver.query(CONTENT_URI, + CellBroadcastDatabaseHelper.QUERY_COLUMNS, null, null, null); + assertThat(cursor.getCount()).isEqualTo(2); + // delete one message + mCellBroadcastProviderTestable.deleteBroadcast(1); + cursor = mContentResolver.query(CONTENT_URI, CellBroadcastDatabaseHelper.QUERY_COLUMNS, + null, null, null); + assertThat(cursor.getCount()).isEqualTo(1); + } + + @Test + public void testInsertQuery() { + // Insert a cell broadcast message + mCellBroadcastProviderTestable.insertNewBroadcast(fakeSmsCbMessage()); + + // Verify that the record is inserted into the database correctly. + Cursor cursor = mContentResolver.query(CONTENT_URI, + CellBroadcastDatabaseHelper.QUERY_COLUMNS, null, null, null); + assertThat(cursor.getCount()).isEqualTo(1); + + cursor.moveToNext(); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.GEOGRAPHICAL_SCOPE))) + .isEqualTo(GEO_SCOPE); + assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.PLMN))) + .isEqualTo(PLMN); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.LAC))).isEqualTo(LAC); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CID))).isEqualTo(CID); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERIAL_NUMBER))) + .isEqualTo(SERIAL_NUMBER); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.SERVICE_CATEGORY))) + .isEqualTo(SERVICE_CATEGORY); + assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.LANGUAGE_CODE))) + .isEqualTo(LANGUAGE_CODE); + assertThat(cursor.getString(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_BODY))) + .isEqualTo(MESSAGE_BODY); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.MESSAGE_PRIORITY))) + .isEqualTo(MESSAGE_PRIORITY); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.ETWS_WARNING_TYPE))) + .isEqualTo(ETWS_WARNING_TYPE); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_MESSAGE_CLASS))) + .isEqualTo(CMAS_MESSAGE_CLASS); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CATEGORY))) + .isEqualTo(CMAS_CATEGORY); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_RESPONSE_TYPE))) + .isEqualTo(CMAS_RESPONSE_TYPE); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_SEVERITY))) + .isEqualTo(CMAS_SEVERITY); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_URGENCY))) + .isEqualTo(CMAS_URGENCY); + assertThat(cursor.getInt(cursor.getColumnIndexOrThrow(CellBroadcasts.CMAS_CERTAINTY))) + .isEqualTo(CMAS_CERTAINTY); + } + + /** + * This is used to give the CellBroadcastContentProviderTest a mocked context which takes a + * CellBroadcastProvider and attaches it to the ContentResolver. + */ + private class MockContextWithProvider extends MockContext { + private final MockContentResolver mResolver; + + MockContextWithProvider(CellBroadcastContentProviderTestable cellBroadcastProvider) { + mResolver = new MockContentResolver(); + cellBroadcastProvider.initializeForTesting(this); + + // Add given cellBroadcastProvider to mResolver, so that mResolver can send queries + // to the provider. + mResolver.addProvider("cellbroadcasts-app", cellBroadcastProvider); + } + + @Override + public MockContentResolver getContentResolver() { + return mResolver; + } + + + @Override + public Object getSystemService(String name) { + Log.d(TAG, "getSystemService: returning null"); + return null; + } + + @Override + public int checkCallingOrSelfPermission(String permission) { + return PackageManager.PERMISSION_GRANTED; + } + } + + private SmsCbMessage fakeSmsCbMessage() { + return new SmsCbMessage(MESSAGE_FORMAT, GEO_SCOPE, SERIAL_NUMBER, + new SmsCbLocation(PLMN, LAC, CID), SERVICE_CATEGORY, LANGUAGE_CODE, 0 , + MESSAGE_BODY, MESSAGE_PRIORITY, new SmsCbEtwsInfo(ETWS_WARNING_TYPE, false, + false, false, null), + new SmsCbCmasInfo(CMAS_MESSAGE_CLASS, CMAS_CATEGORY, CMAS_RESPONSE_TYPE, + CMAS_SEVERITY, CMAS_URGENCY, CMAS_CERTAINTY), 0, null, + System.currentTimeMillis(), 1, 0); + } + } diff --git a/tests/unit/src/com/android/cellbroadcastreceiver/unit/CellBroadcastContentProviderTestable.java b/tests/unit/src/com/android/cellbroadcastreceiver/unit/CellBroadcastContentProviderTestable.java new file mode 100644 index 000000000..8730683cb --- /dev/null +++ b/tests/unit/src/com/android/cellbroadcastreceiver/unit/CellBroadcastContentProviderTestable.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2020 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.cellbroadcastreceiver.unit; + +import android.content.Context; +import android.content.pm.ProviderInfo; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import androidx.test.InstrumentationRegistry; +import com.android.cellbroadcastreceiver.CellBroadcastContentProvider; +import com.android.cellbroadcastreceiver.CellBroadcastDatabaseHelper; + +public class CellBroadcastContentProviderTestable extends CellBroadcastContentProvider { + private static final String TAG = CellBroadcastContentProviderTestable.class.getSimpleName(); + + public CellBroadcastContentProviderTestable() { + } + + @Override + public boolean onCreate() { + // DO NOT call super.onCreate(), otherwise the permission checker will be override. + Log.d(TAG, "CellBroadcastContentProviderTestable onCreate"); + mOpenHelper = new InMemoryCellBroadcastProviderDbHelper(); + return true; + } + + public void closeDatabase() { + mOpenHelper.close(); + } + + public static class InMemoryCellBroadcastProviderDbHelper extends SQLiteOpenHelper { + public InMemoryCellBroadcastProviderDbHelper() { + super(InstrumentationRegistry.getTargetContext(), + null, // db file name is null for in-memory db + null, // CursorFactory is null by default + 1); // db version is no-op for tests + } + + @Override + public void onCreate(SQLiteDatabase db) { + Log.d(TAG, "IN MEMORY DB CREATED"); + db.execSQL(CellBroadcastDatabaseHelper.getStringForCellBroadcastTableCreation( + CellBroadcastDatabaseHelper.TABLE_NAME)); + } + + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {} + } + + public void initializeForTesting(Context context) { + ProviderInfo providerInfo = new ProviderInfo(); + providerInfo.authority = "cellbroadcasts-app"; + + attachInfoForTesting(context, providerInfo); + } +} |
