diff options
Diffstat (limited to 'tests')
5 files changed, 709 insertions, 0 deletions
diff --git a/tests/src/com/android/contacts/NoPermissionsLaunchSmokeTest.java b/tests/src/com/android/contacts/NoPermissionsLaunchSmokeTest.java index 8364b7b07..c9ea3b6aa 100644 --- a/tests/src/com/android/contacts/NoPermissionsLaunchSmokeTest.java +++ b/tests/src/com/android/contacts/NoPermissionsLaunchSmokeTest.java @@ -6,6 +6,7 @@ import android.content.Intent; import android.content.pm.PackageManager; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; +import android.support.test.filters.Suppress; import android.support.test.runner.AndroidJUnit4; import android.support.test.uiautomator.By; import android.support.test.uiautomator.UiDevice; @@ -36,6 +37,8 @@ import static org.junit.Assume.assumeTrue; * -e class com.android.contacts.NoPermissionsLaunchSmokeTest */ @MediumTest +// suppressed because failed assumptions are reported as test failures by the build server +@Suppress @RunWith(AndroidJUnit4.class) public class NoPermissionsLaunchSmokeTest { private static final long TIMEOUT = 5000; diff --git a/tests/src/com/android/contacts/common/database/SimContactDaoTests.java b/tests/src/com/android/contacts/common/database/SimContactDaoTests.java new file mode 100644 index 000000000..5b25eb2b5 --- /dev/null +++ b/tests/src/com/android/contacts/common/database/SimContactDaoTests.java @@ -0,0 +1,359 @@ +/* + * 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.contacts.common.database; + +import android.content.ContentProviderOperation; +import android.content.ContentResolver; +import android.content.Context; +import android.database.Cursor; +import android.database.CursorWrapper; +import android.database.DatabaseUtils; +import android.provider.ContactsContract; +import android.support.annotation.RequiresApi; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.LargeTest; +import android.support.test.filters.SdkSuppress; +import android.support.test.runner.AndroidJUnit4; + +import com.android.contacts.common.model.SimContact; +import com.android.contacts.common.model.account.AccountWithDataSet; +import com.android.contacts.tests.AccountsTestHelper; +import com.android.contacts.tests.SimContactsTestHelper; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.runners.Enclosed; +import org.junit.runner.RunWith; + +import java.util.ArrayList; +import java.util.Arrays; + +import static android.os.Build.VERSION_CODES; +import static org.hamcrest.Matchers.allOf; +import static org.junit.Assert.assertThat; + +import android.support.test.filters.Suppress; + +@RunWith(Enclosed.class) +public class SimContactDaoTests { + + // Lollipop MR1 required for AccountManager.removeAccountExplicitly + @RequiresApi(api = VERSION_CODES.LOLLIPOP_MR1) + @SdkSuppress(minSdkVersion = VERSION_CODES.LOLLIPOP_MR1) + @LargeTest + @RunWith(AndroidJUnit4.class) + public static class ImportIntegrationTest { + private AccountWithDataSet mAccount; + private AccountsTestHelper mAccountsHelper; + private ContentResolver mResolver; + + @Before + public void setUp() throws Exception { + mAccountsHelper = new AccountsTestHelper(); + mAccount = mAccountsHelper.addTestAccount(); + mResolver = getContext().getContentResolver(); + } + + @After + public void tearDown() throws Exception { + mAccountsHelper.cleanup(); + } + + @Test + public void importFromSim() throws Exception { + final SimContactDao sut = new SimContactDao(getContext()); + + sut.importContacts(Arrays.asList( + new SimContact(1, "Test One", "15095550101", null), + new SimContact(2, "Test Two", "15095550102", null), + new SimContact(3, "Test Three", "15095550103", new String[] { + "user@example.com", "user2@example.com" + }) + ), mAccount); + + Cursor cursor = queryContactWithName("Test One"); + assertThat(cursor, hasCount(2)); + assertThat(cursor, hasName("Test One")); + assertThat(cursor, hasPhone("15095550101")); + cursor.close(); + + cursor = queryContactWithName("Test Two"); + assertThat(cursor, hasCount(2)); + assertThat(cursor, hasName("Test Two")); + assertThat(cursor, hasPhone("15095550102")); + cursor.close(); + + cursor = queryContactWithName("Test Three"); + assertThat(cursor, hasCount(4)); + assertThat(cursor, hasName("Test Three")); + assertThat(cursor, hasPhone("15095550103")); + assertThat(cursor, allOf(hasEmail("user@example.com"), hasEmail("user2@example.com"))); + cursor.close(); + } + + @Test + public void importContactWhichOnlyHasName() throws Exception { + final SimContactDao sut = new SimContactDao(getContext()); + + sut.importContacts(Arrays.asList( + new SimContact(1, "Test importJustName", null, null) + ), mAccount); + + Cursor cursor = queryAllDataInAccount(); + + assertThat(cursor, hasCount(1)); + assertThat(cursor, hasName("Test importJustName")); + cursor.close(); + } + + @Test + public void importContactWhichOnlyHasPhone() throws Exception { + final SimContactDao sut = new SimContactDao(getContext()); + + sut.importContacts(Arrays.asList( + new SimContact(1, null, "15095550111", null) + ), mAccount); + + Cursor cursor = queryAllDataInAccount(); + + assertThat(cursor, hasCount(1)); + assertThat(cursor, hasPhone("15095550111")); + cursor.close(); + } + + @Test + public void ignoresEmptyContacts() throws Exception { + final SimContactDao sut = new SimContactDao(getContext()); + + // This probably isn't possible but we'll test it to demonstrate expected behavior and + // just in case it does occur + sut.importContacts(Arrays.asList( + new SimContact(1, null, null, null), + new SimContact(2, null, null, null), + new SimContact(3, null, null, null), + new SimContact(4, "Not null", null, null) + ), mAccount); + + final Cursor contactsCursor = queryAllRawContactsInAccount(); + assertThat(contactsCursor, hasCount(1)); + contactsCursor.close(); + + final Cursor dataCursor = queryAllDataInAccount(); + assertThat(dataCursor, hasCount(1)); + + dataCursor.close(); + } + + private Cursor queryAllRawContactsInAccount() { + return new StringableCursor(mResolver.query(ContactsContract.RawContacts.CONTENT_URI, null, + ContactsContract.RawContacts.ACCOUNT_NAME + "=? AND " + + ContactsContract.RawContacts.ACCOUNT_TYPE+ "=?", + new String[] { + mAccount.name, + mAccount.type + }, null)); + } + + private Cursor queryAllDataInAccount() { + return new StringableCursor(mResolver.query(ContactsContract.Data.CONTENT_URI, null, + ContactsContract.RawContacts.ACCOUNT_NAME + "=? AND " + + ContactsContract.RawContacts.ACCOUNT_TYPE+ "=?", + new String[] { + mAccount.name, + mAccount.type + }, null)); + } + + private Cursor queryContactWithName(String name) { + return new StringableCursor(mResolver.query(ContactsContract.Data.CONTENT_URI, null, + ContactsContract.RawContacts.ACCOUNT_NAME + "=? AND " + + ContactsContract.RawContacts.ACCOUNT_TYPE+ "=? AND " + + ContactsContract.Data.DISPLAY_NAME + "=?", + new String[] { + mAccount.name, + mAccount.type, + name + }, null)); + } + } + + @LargeTest + // suppressed because failed assumptions are reported as test failures by the build server + @Suppress + @RunWith(AndroidJUnit4.class) + public static class ReadIntegrationTest { + private SimContactsTestHelper mSimTestHelper; + private ArrayList<ContentProviderOperation> mSimSnapshot; + + @Before + public void setUp() throws Exception { + mSimTestHelper = new SimContactsTestHelper(); + + mSimTestHelper.assumeSimWritable(); + if (!mSimTestHelper.isSimWritable()) return; + + mSimSnapshot = mSimTestHelper.captureRestoreSnapshot(); + mSimTestHelper.deleteAllSimContacts(); + } + + @After + public void tearDown() throws Exception { + mSimTestHelper.restore(mSimSnapshot); + } + + @Test + public void readFromSim() { + mSimTestHelper.addSimContact("Test Simone", "15095550101"); + mSimTestHelper.addSimContact("Test Simtwo", "15095550102"); + mSimTestHelper.addSimContact("Test Simthree", "15095550103"); + + final SimContactDao sut = new SimContactDao(getContext()); + final ArrayList<SimContact> contacts = sut.loadSimContacts(); + + assertThat(contacts.get(0), isSimContactWithNameAndPhone("Test Simone", "15095550101")); + assertThat(contacts.get(1), isSimContactWithNameAndPhone("Test Simtwo", "15095550102")); + assertThat(contacts.get(2), isSimContactWithNameAndPhone("Test Simthree", "15095550103")); + } + } + + private static Matcher<SimContact> isSimContactWithNameAndPhone(final String name, + final String phone) { + return new BaseMatcher<SimContact>() { + @Override + public boolean matches(Object o) { + if (!(o instanceof SimContact)) return false; + + SimContact other = (SimContact) o; + + return name.equals(other.getName()) + && phone.equals(other.getPhone()); + } + + @Override + public void describeTo(Description description) { + description.appendText("SimContact with name=" + name + " and phone=" + + phone); + } + }; + } + + private static Matcher<Cursor> hasCount(final int count) { + return new BaseMatcher<Cursor>() { + @Override + public boolean matches(Object o) { + if (!(o instanceof Cursor)) return false; + return ((Cursor)o).getCount() == count; + } + + @Override + public void describeTo(Description description) { + description.appendText("Cursor with " + count + " rows"); + } + }; + } + + private static Matcher<Cursor> hasMimeType(String type) { + return hasValueForColumn(ContactsContract.Data.MIMETYPE, type); + } + + private static Matcher<Cursor> hasValueForColumn(final String column, final String value) { + return new BaseMatcher<Cursor>() { + + @Override + public boolean matches(Object o) { + if (!(o instanceof Cursor)) return false; + final Cursor cursor = (Cursor)o; + + final int index = cursor.getColumnIndexOrThrow(column); + return value.equals(cursor.getString(index)); + } + + @Override + public void describeTo(Description description) { + description.appendText("Cursor with " + column + "=" + value); + } + }; + } + + private static Matcher<Cursor> hasRowMatching(final Matcher<Cursor> rowMatcher) { + return new BaseMatcher<Cursor>() { + @Override + public boolean matches(Object o) { + if (!(o instanceof Cursor)) return false; + final Cursor cursor = (Cursor)o; + + cursor.moveToPosition(-1); + while (cursor.moveToNext()) { + if (rowMatcher.matches(cursor)) return true; + } + + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("Cursor with row matching "); + rowMatcher.describeTo(description); + } + }; + } + + private static Matcher<Cursor> hasName(final String name) { + return hasRowMatching(allOf( + hasMimeType(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE), + hasValueForColumn( + ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, name))); + } + + private static Matcher<Cursor> hasPhone(final String phone) { + return hasRowMatching(allOf( + hasMimeType(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE), + hasValueForColumn( + ContactsContract.CommonDataKinds.Phone.NUMBER, phone))); + } + + private static Matcher<Cursor> hasEmail(final String email) { + return hasRowMatching(allOf( + hasMimeType(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE), + hasValueForColumn( + ContactsContract.CommonDataKinds.Email.ADDRESS, email))); + } + + static class StringableCursor extends CursorWrapper { + public StringableCursor(Cursor cursor) { + super(cursor); + } + + @Override + public String toString() { + final Cursor wrapped = getWrappedCursor(); + + if (wrapped.getCount() == 0) { + return "Empty Cursor"; + } + + return DatabaseUtils.dumpCursorToString(wrapped); + } + } + + static Context getContext() { + return InstrumentationRegistry.getTargetContext(); + } +} diff --git a/tests/src/com/android/contacts/common/model/SimContactTests.java b/tests/src/com/android/contacts/common/model/SimContactTests.java new file mode 100644 index 000000000..de9ab5a1f --- /dev/null +++ b/tests/src/com/android/contacts/common/model/SimContactTests.java @@ -0,0 +1,43 @@ +package com.android.contacts.common.model; + +import android.os.Parcel; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Created by mhagerott on 10/6/16. + */ + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class SimContactTests { + @Test + public void parcelRoundtrip() { + assertParcelsCorrectly(new SimContact(1, "name1", "phone1", + new String[] { "email1a", "email1b" })); + assertParcelsCorrectly(new SimContact(2, "name2", "phone2", null)); + assertParcelsCorrectly(new SimContact(3, "name3", null, + new String[] { "email3" })); + assertParcelsCorrectly(new SimContact(4, null, "phone4", + new String[] { "email4" })); + assertParcelsCorrectly(new SimContact(5, null, null, null)); + assertParcelsCorrectly(new SimContact(6, "name6", "phone6", + new String[0])); + } + + private void assertParcelsCorrectly(SimContact contact) { + final Parcel parcel = Parcel.obtain(); + parcel.writeParcelable(contact, 0); + parcel.setDataPosition(0); + final SimContact unparceled = parcel.readParcelable( + SimContact.class.getClassLoader()); + assertThat(unparceled, equalTo(contact)); + parcel.recycle(); + } +} diff --git a/tests/src/com/android/contacts/tests/AccountsTestHelper.java b/tests/src/com/android/contacts/tests/AccountsTestHelper.java new file mode 100644 index 000000000..be826f7ec --- /dev/null +++ b/tests/src/com/android/contacts/tests/AccountsTestHelper.java @@ -0,0 +1,106 @@ +/* + * 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.contacts.tests; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.content.ContentResolver; +import android.content.Context; +import android.os.Build; +import android.provider.ContactsContract.RawContacts; +import android.support.annotation.NonNull; +import android.support.annotation.RequiresApi; +import android.support.test.InstrumentationRegistry; + +import com.android.contacts.common.model.account.AccountWithDataSet; + +import static junit.framework.Assert.assertNotNull; +import static junit.framework.Assert.assertTrue; + +@SuppressWarnings("MissingPermission") +public class AccountsTestHelper { + public static final String TEST_ACCOUNT_TYPE = "com.android.contacts.tests.testauth.basic"; + + private final Context mContext; + private final AccountManager mAccountManager; + private final ContentResolver mResolver; + + private Account mTestAccount; + + public AccountsTestHelper() { + // Use context instead of target context because the test package has the permissions needed + // to add and remove accounts. + this(InstrumentationRegistry.getContext()); + } + + public AccountsTestHelper(Context context) { + mContext = context; + mAccountManager = AccountManager.get(mContext); + mResolver = mContext.getContentResolver(); + } + + public AccountWithDataSet addTestAccount() { + return addTestAccount(generateAccountName()); + } + + public String generateAccountName(String prefix) { + return prefix + "_t" + System.nanoTime(); + } + + public String generateAccountName() { + return generateAccountName("test"); + } + + public AccountWithDataSet addTestAccount(@NonNull String name) { + // remember the most recent one. If the caller wants to add multiple accounts they will + // have to keep track of them themselves. + mTestAccount = new Account(name, TEST_ACCOUNT_TYPE); + assertTrue(mAccountManager.addAccountExplicitly(mTestAccount, null, null)); + return convertTestAccount(); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1) + public void removeTestAccount(AccountWithDataSet account) { + final Account remove = account.getAccountOrNull(); + mAccountManager.removeAccountExplicitly(remove); + } + + public void removeContactsForAccount() { + // Not sure if this is necessary or if contacts are automatically cleaned up when the + // account is removed. + mResolver.delete(RawContacts.CONTENT_URI, + RawContacts.ACCOUNT_NAME + "=? AND " + RawContacts.ACCOUNT_TYPE + "=?", + new String[] { mTestAccount.name, mTestAccount.type }); + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP_MR1) + public void cleanup() { + assertNotNull(mTestAccount); + + // Note that we don't need to cleanup up the contact data associated with the account. + // CP2 will eventually do that automatically so as long as we're using unique account + // names we should be safe. Note that cleanup is not done synchronously when the account + // is removed so if multiple tests are using the same account name then the data should + // be manually deleted after each test run. + + mAccountManager.removeAccountExplicitly(mTestAccount); + mTestAccount = null; + } + + private AccountWithDataSet convertTestAccount() { + return new AccountWithDataSet(mTestAccount.name, mTestAccount.type, null); + } +} diff --git a/tests/src/com/android/contacts/tests/SimContactsTestHelper.java b/tests/src/com/android/contacts/tests/SimContactsTestHelper.java new file mode 100644 index 000000000..45ac8d96f --- /dev/null +++ b/tests/src/com/android/contacts/tests/SimContactsTestHelper.java @@ -0,0 +1,198 @@ +/* + * 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.contacts.tests; + +import android.content.ContentProvider; +import android.content.ContentProviderOperation; +import android.content.ContentProviderResult; +import android.content.ContentResolver; +import android.content.ContentValues; +import android.content.Context; +import android.content.OperationApplicationException; +import android.database.Cursor; +import android.net.Uri; +import android.os.RemoteException; +import android.support.annotation.NonNull; +import android.support.test.InstrumentationRegistry; +import android.telephony.TelephonyManager; + +import com.android.contacts.common.model.SimContact; +import com.android.contacts.common.database.SimContactDao; +import com.android.contacts.common.test.mocks.MockContentProvider; + +import java.util.ArrayList; +import java.util.List; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assume.assumeThat; +import static org.junit.Assume.assumeTrue; + +public class SimContactsTestHelper { + + private final Context mContext; + private final TelephonyManager mTelephonyManager; + private final ContentResolver mResolver; + private final SimContactDao mSimDao; + + public SimContactsTestHelper() { + this(InstrumentationRegistry.getTargetContext()); + } + + public SimContactsTestHelper(Context context) { + mContext = context; + mResolver = context.getContentResolver(); + mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); + mSimDao = new SimContactDao(context); + } + + public int getSimContactCount() { + Cursor cursor = mContext.getContentResolver().query(SimContactDao.ICC_CONTENT_URI, + null, null, null, null); + try { + return cursor.getCount(); + } finally { + cursor.close(); + } + } + + public ContentValues iccRow(long id, String name, String number, String emails) { + ContentValues values = new ContentValues(); + values.put(SimContactDao._ID, id); + values.put(SimContactDao.NAME, name); + values.put(SimContactDao.NUMBER, number); + values.put(SimContactDao.EMAILS, emails); + return values; + } + + public ContentProvider iccProviderExpectingNoQueries() { + return new MockContentProvider(); + } + + public ContentProvider emptyIccProvider() { + final MockContentProvider provider = new MockContentProvider(); + provider.expectQuery(SimContactDao.ICC_CONTENT_URI) + .withDefaultProjection( + SimContactDao._ID, SimContactDao.NAME, + SimContactDao.NUMBER, SimContactDao.EMAILS) + .withAnyProjection() + .withAnySelection() + .withAnySortOrder() + .returnEmptyCursor(); + return provider; + } + + public Uri addSimContact(String name, String number) { + ContentValues values = new ContentValues(); + // Oddly even though it's called name when querying we have to use "tag" for it to work + // when inserting. + if (name != null) { + values.put("tag", name); + } + if (number != null) { + values.put(SimContactDao.NUMBER, number); + } + return mResolver.insert(SimContactDao.ICC_CONTENT_URI, values); + } + + public ContentProviderResult[] deleteAllSimContacts() + throws RemoteException, OperationApplicationException { + SimContactDao dao = new SimContactDao(mContext); + List<SimContact> contacts = dao.loadSimContacts(); + ArrayList<ContentProviderOperation> ops = new ArrayList<>(); + for (SimContact contact : contacts) { + ops.add(ContentProviderOperation + .newDelete(SimContactDao.ICC_CONTENT_URI) + .withSelection(getWriteSelection(contact), null) + .build()); + } + return mResolver.applyBatch(SimContactDao.ICC_CONTENT_URI.getAuthority(), ops); + } + + public ContentProviderResult[] restore(ArrayList<ContentProviderOperation> restoreOps) + throws RemoteException, OperationApplicationException { + if (restoreOps == null) return null; + + // Remove SIM contacts because we assume that caller wants the data to be in the exact + // state as when the restore ops were captured. + deleteAllSimContacts(); + return mResolver.applyBatch(SimContactDao.ICC_CONTENT_URI.getAuthority(), restoreOps); + } + + public ArrayList<ContentProviderOperation> captureRestoreSnapshot() { + ArrayList<SimContact> contacts = mSimDao.loadSimContacts(); + + ArrayList<ContentProviderOperation> ops = new ArrayList<>(); + for (SimContact contact : contacts) { + final String[] emails = contact.getEmails(); + if (emails != null && emails.length > 0) { + throw new IllegalStateException("Cannot restore emails." + + " Please manually remove SIM contacts with emails."); + } + ops.add(ContentProviderOperation + .newInsert(SimContactDao.ICC_CONTENT_URI) + .withValue("tag", contact.getName()) + .withValue("number", contact.getPhone()) + .build()); + } + return ops; + } + + public String getWriteSelection(SimContact simContact) { + return "tag='" + simContact.getName() + "' AND " + SimContactDao.NUMBER + "='" + + simContact.getPhone() + "'"; + } + + public int deleteSimContact(@NonNull String name, @NonNull String number) { + // IccProvider doesn't use the selection args. + final String selection = "tag='" + name + "' AND " + + SimContactDao.NUMBER + "='" + number + "'"; + return mResolver.delete(SimContactDao.ICC_CONTENT_URI, selection, null); + } + + public boolean isSimReady() { + return mTelephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY; + } + + public boolean doesSimHaveContacts() { + return isSimReady() && getSimContactCount() > 0; + } + + public boolean isSimWritable() { + if (!isSimReady()) return false; + final String name = "writabeProbe" + System.nanoTime(); + final Uri uri = addSimContact(name, "15095550101"); + return uri != null && deleteSimContact(name, "15095550101") == 1; + } + + public void assumeSimReady() { + assumeTrue(isSimReady()); + } + + public void assumeHasSimContacts() { + assumeTrue(doesSimHaveContacts()); + } + + public void assumeSimCardAbsent() { + assumeThat(mTelephonyManager.getSimState(), equalTo(TelephonyManager.SIM_STATE_ABSENT)); + } + + // The emulator reports SIM_STATE_READY but writes are ignored. This verifies that the + // device will actually persist writes to the SIM card. + public void assumeSimWritable() { + assumeSimReady(); + assumeTrue(isSimWritable()); + } +} |