From c70343becd3734fd380e0d20f05b7605e6233d43 Mon Sep 17 00:00:00 2001 From: Sarmad Hashmi Date: Thu, 10 Mar 2016 20:22:43 -0800 Subject: Refactor voicemail archive code. +Created new class for all AsyncTasks and listener interfaces. +Separated the archive code into separate methods +Added 7 tests BUG=22797391 Change-Id: I789125328bf079846e34c5fd57fd0d1c67dc6266 --- .../dialer/voicemail/VoicemailAsyncTaskUtil.java | 346 ++++++++++++++++++ .../voicemail/VoicemailAsyncTaskUtilTest.java | 388 +++++++++++++++++++++ 2 files changed, 734 insertions(+) create mode 100644 src/com/android/dialer/voicemail/VoicemailAsyncTaskUtil.java create mode 100644 tests/src/com/android/dialer/voicemail/VoicemailAsyncTaskUtilTest.java diff --git a/src/com/android/dialer/voicemail/VoicemailAsyncTaskUtil.java b/src/com/android/dialer/voicemail/VoicemailAsyncTaskUtil.java new file mode 100644 index 000000000..7abf9a72c --- /dev/null +++ b/src/com/android/dialer/voicemail/VoicemailAsyncTaskUtil.java @@ -0,0 +1,346 @@ +/* + * 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.dialer.voicemail; + +import com.android.contacts.common.testing.NeededForTesting; +import com.android.dialer.calllog.CallLogQuery; +import com.android.dialer.database.VoicemailArchiveContract; +import com.android.dialer.util.AsyncTaskExecutor; +import com.android.dialer.util.AsyncTaskExecutors; +import com.google.common.base.Preconditions; +import com.google.common.io.ByteStreams; + +import android.content.ContentResolver; +import android.content.ContentUris; +import android.content.ContentValues; +import android.database.Cursor; +import android.net.Uri; +import android.os.AsyncTask; +import android.provider.CallLog; +import android.provider.VoicemailContract; +import android.util.Log; +import com.android.common.io.MoreCloseables; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +import javax.annotation.Nullable; + +/** + * Class containing asynchronous tasks for voicemails. + */ +@NeededForTesting +public class VoicemailAsyncTaskUtil { + private static final String TAG = "VoicemailAsyncTaskUtil"; + + /** The enumeration of {@link AsyncTask} objects we use in this class. */ + public enum Tasks { + GET_VOICEMAIL_FILE_PATH, + SET_VOICEMAIL_ARCHIVE_STATUS, + ARCHIVE_VOICEMAIL_CONTENT + } + + @NeededForTesting + public interface OnArchiveVoicemailListener { + /** + * Called after the voicemail has been archived. + * + * @param archivedVoicemailUri the URI of the archived voicemail + */ + void onArchiveVoicemail(@Nullable Uri archivedVoicemailUri); + } + + @NeededForTesting + public interface OnSetVoicemailArchiveStatusListener { + /** + * Called after the voicemail archived_by_user column is updated. + * + * @param success whether the update was successful or not + */ + void onSetVoicemailArchiveStatus(boolean success); + } + + @NeededForTesting + public interface OnGetArchivedVoicemailFilePathListener { + /** + * Called after the voicemail file path is obtained. + * + * @param filePath the file path of the archived voicemail + */ + void onGetArchivedVoicemailFilePath(@Nullable String filePath); + } + + private final ContentResolver mResolver; + private final AsyncTaskExecutor mAsyncTaskExecutor; + + @NeededForTesting + public VoicemailAsyncTaskUtil(ContentResolver contentResolver) { + mResolver = Preconditions.checkNotNull(contentResolver); + mAsyncTaskExecutor = AsyncTaskExecutors.createThreadPoolExecutor(); + } + + /** + * Returns the archived voicemail file path. + */ + @NeededForTesting + public void getVoicemailFilePath( + final OnGetArchivedVoicemailFilePathListener listener, + final Uri voicemailUri) { + Preconditions.checkNotNull(listener); + Preconditions.checkNotNull(voicemailUri); + mAsyncTaskExecutor.submit(Tasks.GET_VOICEMAIL_FILE_PATH, + new AsyncTask() { + @Nullable + @Override + protected String doInBackground(Void... params) { + try (Cursor cursor = mResolver.query(voicemailUri, + new String[]{VoicemailArchiveContract.VoicemailArchive._DATA}, + null, null, null)) { + if (hasContent(cursor)) { + return cursor.getString(cursor.getColumnIndex( + VoicemailArchiveContract.VoicemailArchive._DATA)); + } + } + return null; + } + + @Override + protected void onPostExecute(String filePath) { + listener.onGetArchivedVoicemailFilePath(filePath); + } + }); + } + + /** + * Updates the archived_by_user flag of the archived voicemail. + */ + @NeededForTesting + public void setVoicemailArchiveStatus( + final OnSetVoicemailArchiveStatusListener listener, + final Uri voicemailUri, + final boolean archivedByUser) { + Preconditions.checkNotNull(listener); + Preconditions.checkNotNull(voicemailUri); + mAsyncTaskExecutor.submit(Tasks.SET_VOICEMAIL_ARCHIVE_STATUS, + new AsyncTask() { + @Override + protected Boolean doInBackground(Void... params) { + ContentValues values = new ContentValues(1); + values.put(VoicemailArchiveContract.VoicemailArchive.ARCHIVED, + archivedByUser); + return mResolver.update(voicemailUri, values, null, null) > 0; + } + + @Override + protected void onPostExecute(Boolean success) { + listener.onSetVoicemailArchiveStatus(success); + } + }); + } + + /** + * Checks if a voicemail has already been archived, if so, return the previously archived URI. + * Otherwise, copy the voicemail information to the local dialer database. If archive was + * successful, archived voicemail URI is returned to listener, otherwise null. + */ + @NeededForTesting + public void archiveVoicemailContent( + final OnArchiveVoicemailListener listener, + final Uri voicemailUri) { + Preconditions.checkNotNull(listener); + Preconditions.checkNotNull(voicemailUri); + mAsyncTaskExecutor.submit(Tasks.ARCHIVE_VOICEMAIL_CONTENT, + new AsyncTask() { + @Nullable + @Override + protected Uri doInBackground(Void... params) { + Uri archivedVoicemailUri = getArchivedVoicemailUri(voicemailUri); + + // If previously archived, return uri, otherwise archive everything. + if (archivedVoicemailUri != null) { + return archivedVoicemailUri; + } + + // Combine call log and voicemail content info. + ContentValues values = getVoicemailContentValues(voicemailUri); + if (values == null) { + return null; + } + + Uri insertedVoicemailUri = mResolver.insert( + VoicemailArchiveContract.VoicemailArchive.CONTENT_URI, values); + if (insertedVoicemailUri == null) { + return null; + } + + // Copy voicemail content to a new file. + boolean copiedFile = false; + try (InputStream inputStream = mResolver.openInputStream(voicemailUri); + OutputStream outputStream = + mResolver.openOutputStream(insertedVoicemailUri)) { + if (inputStream != null && outputStream != null) { + ByteStreams.copy(inputStream, outputStream); + copiedFile = true; + return insertedVoicemailUri; + } + } catch (IOException e) { + Log.w(TAG, "Failed to copy voicemail content to new file: " + + e.toString()); + } finally { + if (!copiedFile) { + // Roll back insert if the voicemail content was not copied. + mResolver.delete(insertedVoicemailUri, null, null); + } + } + return null; + } + + @Override + protected void onPostExecute(Uri archivedVoicemailUri) { + listener.onArchiveVoicemail(archivedVoicemailUri); + } + }); + } + + /** + * Helper method to get the archived URI of a voicemail. + * + * @param voicemailUri a {@link android.provider.VoicemailContract.Voicemails#CONTENT_URI} URI. + * @return the URI of the archived voicemail or {@code null} + */ + @Nullable + private Uri getArchivedVoicemailUri(Uri voicemailUri) { + try (Cursor cursor = getArchiveExistsCursor(voicemailUri)) { + if (hasContent(cursor)) { + return VoicemailArchiveContract.VoicemailArchive + .buildWithId(cursor.getInt(cursor.getColumnIndex( + VoicemailArchiveContract.VoicemailArchive._ID))); + } + } + return null; + } + + /** + * Helper method to make a copy of all the values needed to display a voicemail. + * + * @param voicemailUri a {@link VoicemailContract.Voicemails#CONTENT_URI} URI. + * @return the combined call log and voicemail values for the given URI, or {@code null} + */ + @Nullable + private ContentValues getVoicemailContentValues(Uri voicemailUri) { + try (Cursor callLogInfo = getCallLogInfoCursor(voicemailUri); + Cursor contentInfo = getContentInfoCursor(voicemailUri)) { + + if (hasContent(callLogInfo) && hasContent(contentInfo)) { + // Create values to insert into database. + ContentValues values = new ContentValues(); + + // Insert voicemail call log info. + values.put(VoicemailArchiveContract.VoicemailArchive.COUNTRY_ISO, + callLogInfo.getString(CallLogQuery.COUNTRY_ISO)); + values.put(VoicemailArchiveContract.VoicemailArchive.GEOCODED_LOCATION, + callLogInfo.getString(CallLogQuery.GEOCODED_LOCATION)); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NAME, + callLogInfo.getString(CallLogQuery.CACHED_NAME)); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_TYPE, + callLogInfo.getInt(CallLogQuery.CACHED_NUMBER_TYPE)); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_LABEL, + callLogInfo.getString(CallLogQuery.CACHED_NUMBER_LABEL)); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_LOOKUP_URI, + callLogInfo.getString(CallLogQuery.CACHED_LOOKUP_URI)); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_MATCHED_NUMBER, + callLogInfo.getString(CallLogQuery.CACHED_MATCHED_NUMBER)); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NORMALIZED_NUMBER, + callLogInfo.getString(CallLogQuery.CACHED_NORMALIZED_NUMBER)); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_FORMATTED_NUMBER, + callLogInfo.getString(CallLogQuery.CACHED_FORMATTED_NUMBER)); + values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER_PRESENTATION, + callLogInfo.getInt(CallLogQuery.NUMBER_PRESENTATION)); + values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_COMPONENT_NAME, + callLogInfo.getString(CallLogQuery.ACCOUNT_COMPONENT_NAME)); + values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_ID, + callLogInfo.getString(CallLogQuery.ACCOUNT_ID)); + values.put(VoicemailArchiveContract.VoicemailArchive.FEATURES, + callLogInfo.getInt(CallLogQuery.FEATURES)); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_PHOTO_URI, + callLogInfo.getString(CallLogQuery.CACHED_PHOTO_URI)); + + // Insert voicemail content info. + values.put(VoicemailArchiveContract.VoicemailArchive.SERVER_ID, + contentInfo.getInt(contentInfo.getColumnIndex( + VoicemailContract.Voicemails._ID))); + values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER, + contentInfo.getString(contentInfo.getColumnIndex( + VoicemailContract.Voicemails.NUMBER))); + values.put(VoicemailArchiveContract.VoicemailArchive.DATE, + contentInfo.getLong(contentInfo.getColumnIndex( + VoicemailContract.Voicemails.DATE))); + values.put(VoicemailArchiveContract.VoicemailArchive.DURATION, + contentInfo.getLong(contentInfo.getColumnIndex( + VoicemailContract.Voicemails.DURATION))); + values.put(VoicemailArchiveContract.VoicemailArchive.MIME_TYPE, + contentInfo.getString(contentInfo.getColumnIndex( + VoicemailContract.Voicemails.MIME_TYPE))); + values.put(VoicemailArchiveContract.VoicemailArchive.TRANSCRIPTION, + contentInfo.getString(contentInfo.getColumnIndex( + VoicemailContract.Voicemails.TRANSCRIPTION))); + + // Achived is false by default because it is updated after insertion. + values.put(VoicemailArchiveContract.VoicemailArchive.ARCHIVED, false); + + return values; + } + } + return null; + } + + private boolean hasContent(@Nullable Cursor cursor) { + return cursor != null && cursor.moveToFirst(); + } + + @Nullable + private Cursor getCallLogInfoCursor(Uri voicemailUri) { + return mResolver.query( + ContentUris.withAppendedId(CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL, + ContentUris.parseId(voicemailUri)), + CallLogQuery._PROJECTION, null, null, null); + } + + @Nullable + private Cursor getContentInfoCursor(Uri voicemailUri) { + return mResolver.query(voicemailUri, + new String[] { + VoicemailContract.Voicemails._ID, + VoicemailContract.Voicemails.NUMBER, + VoicemailContract.Voicemails.DATE, + VoicemailContract.Voicemails.DURATION, + VoicemailContract.Voicemails.MIME_TYPE, + VoicemailContract.Voicemails.TRANSCRIPTION, + }, null, null, null); + } + + @Nullable + private Cursor getArchiveExistsCursor(Uri voicemailUri) { + return mResolver.query(VoicemailArchiveContract.VoicemailArchive.CONTENT_URI, + new String[] {VoicemailArchiveContract.VoicemailArchive._ID}, + VoicemailArchiveContract.VoicemailArchive.SERVER_ID + "=" + + ContentUris.parseId(voicemailUri), + null, + null); + } +} diff --git a/tests/src/com/android/dialer/voicemail/VoicemailAsyncTaskUtilTest.java b/tests/src/com/android/dialer/voicemail/VoicemailAsyncTaskUtilTest.java new file mode 100644 index 000000000..d98d9fa59 --- /dev/null +++ b/tests/src/com/android/dialer/voicemail/VoicemailAsyncTaskUtilTest.java @@ -0,0 +1,388 @@ +/* + * 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.dialer.voicemail; + +import android.content.ContentUris; +import android.content.ContentValues; +import android.content.res.AssetFileDescriptor; +import android.net.Uri; +import android.os.Bundle; +import android.os.ParcelFileDescriptor; +import android.provider.CallLog; +import android.provider.VoicemailContract; +import android.test.InstrumentationTestCase; +import android.test.mock.MockContentResolver; + +import com.android.contacts.common.test.mocks.MockContentProvider; +import com.android.contacts.common.test.mocks.MockContentProvider.Query; +import com.android.dialer.calllog.CallLogQuery; +import com.android.dialer.database.VoicemailArchiveContract; +import com.android.dialer.util.AsyncTaskExecutors; +import com.android.dialer.util.FakeAsyncTaskExecutor; +import com.android.dialer.voicemail.VoicemailAsyncTaskUtil.OnGetArchivedVoicemailFilePathListener; +import com.android.dialer.voicemail.VoicemailAsyncTaskUtil.OnArchiveVoicemailListener; +import com.android.dialer.voicemail.VoicemailAsyncTaskUtil.OnSetVoicemailArchiveStatusListener; + +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +import static org.mockito.Mockito.*; + +import java.io.FileNotFoundException; +import java.io.IOException; + +public class VoicemailAsyncTaskUtilTest extends InstrumentationTestCase { + private static final String TEST_MIME_TYPE = "audio/mp3"; + private static final String TEST_NUMBER = "+1412555555"; + private static final String TEST_FILE_PATH = "TEST_PATH"; + private static final String TEST_TRANSCRIPTION = "TEST_TRANSCRIPTION"; + private static final long TEST_DATE = 0; + private static final long TEST_DURATION = 0; + private static final int TEST_SERVER_ID = 1; + private static final int TEST_ID = 2; + private static final Uri ARCHIVED_VOICEMAIL_URI = + VoicemailArchiveContract.VoicemailArchive.buildWithId(TEST_ID); + private static final Uri VOICEMAIL_URI = VoicemailContract.Voicemails.CONTENT_URI + .buildUpon().appendPath(Integer.toString(TEST_SERVER_ID)).build(); + private static final String[] CALLLOG_QUERY_PROJECTION = new String[] { + CallLog.Calls._ID, + CallLog.Calls.NUMBER, + CallLog.Calls.DATE, + CallLog.Calls.DURATION, + CallLog.Calls.TYPE, + CallLog.Calls.COUNTRY_ISO, + CallLog.Calls.VOICEMAIL_URI, + CallLog.Calls.GEOCODED_LOCATION, + CallLog.Calls.CACHED_NAME, + CallLog.Calls.CACHED_NUMBER_TYPE, + CallLog.Calls.CACHED_NUMBER_LABEL, + CallLog.Calls.CACHED_LOOKUP_URI, + CallLog.Calls.CACHED_MATCHED_NUMBER, + CallLog.Calls.CACHED_NORMALIZED_NUMBER, + CallLog.Calls.CACHED_PHOTO_ID, + CallLog.Calls.CACHED_FORMATTED_NUMBER, + CallLog.Calls.IS_READ, + CallLog.Calls.NUMBER_PRESENTATION, + CallLog.Calls.PHONE_ACCOUNT_COMPONENT_NAME, + CallLog.Calls.PHONE_ACCOUNT_ID, + CallLog.Calls.FEATURES, + CallLog.Calls.DATA_USAGE, + CallLog.Calls.TRANSCRIPTION, + CallLog.Calls.CACHED_PHOTO_URI + }; + private static final String[] VOICEMAIL_PROJECTION = new String[] { + VoicemailContract.Voicemails._ID, + VoicemailContract.Voicemails.NUMBER, + VoicemailContract.Voicemails.DATE, + VoicemailContract.Voicemails.DURATION, + VoicemailContract.Voicemails.MIME_TYPE, + VoicemailContract.Voicemails.TRANSCRIPTION, + }; + + private final MockContentResolver mContentResolver = new MockContentResolver(); + private final MockContentProvider mArchiveContentProvider = new TestVoicemailContentProvider(); + private final MockContentProvider mVoicemailContentProvider = + new TestVoicemailContentProvider(); + private final MockContentProvider mCallLogContentProvider = new MockContentProvider(); + @Rule + private final TemporaryFolder mTemporaryFolder = new TemporaryFolder(); + + private VoicemailAsyncTaskUtil mVoicemailAsyncTaskUtil; + private FakeAsyncTaskExecutor mFakeAsyncTaskExecutor; + + @Override + protected void setUp() throws Exception { + super.setUp(); + mFakeAsyncTaskExecutor = new FakeAsyncTaskExecutor(getInstrumentation()); + AsyncTaskExecutors.setFactoryForTest(mFakeAsyncTaskExecutor.getFactory()); + mContentResolver.addProvider(VoicemailArchiveContract.AUTHORITY, mArchiveContentProvider); + mContentResolver.addProvider(VoicemailContract.AUTHORITY, mVoicemailContentProvider); + mContentResolver.addProvider(CallLog.AUTHORITY, mCallLogContentProvider); + mVoicemailAsyncTaskUtil = new VoicemailAsyncTaskUtil(mContentResolver); + } + + @Override + protected void tearDown() throws Exception { + AsyncTaskExecutors.setFactoryForTest(null); + super.tearDown(); + } + + public void testGetVoicemailFilePath_VoicemailExists() throws Throwable { + newVoicemailArchiveQuery().withAnyProjection() + .returnRow(getCombinedContentValuesWithData()); + final OnGetArchivedVoicemailFilePathListener listener = + mock(OnGetArchivedVoicemailFilePathListener.class); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + mVoicemailAsyncTaskUtil.getVoicemailFilePath(listener, ARCHIVED_VOICEMAIL_URI); + } + }); + mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.GET_VOICEMAIL_FILE_PATH); + verify(listener).onGetArchivedVoicemailFilePath(TEST_FILE_PATH); + verifyQueries(); + } + + public void testGetVoicemailFilePath_VoicemailNotExists() throws Throwable { + newVoicemailArchiveFakeQuery().withAnyProjection().returnEmptyCursor(); + final OnGetArchivedVoicemailFilePathListener listener = + mock(OnGetArchivedVoicemailFilePathListener.class); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + mVoicemailAsyncTaskUtil.getVoicemailFilePath(listener, getFakeVoicemailUri()); + } + }); + mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.GET_VOICEMAIL_FILE_PATH); + verify(listener).onGetArchivedVoicemailFilePath(null); + verifyQueries(); + } + + public void testSetVoicemailArchiveStatus_VoicemailNotExists() throws Throwable { + newVoicemailArchiveNotExistsUpdateQuery(true); + final OnSetVoicemailArchiveStatusListener listener = + mock(OnSetVoicemailArchiveStatusListener.class); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + mVoicemailAsyncTaskUtil.setVoicemailArchiveStatus(listener, + getFakeVoicemailUri(), true); + } + }); + mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.SET_VOICEMAIL_ARCHIVE_STATUS); + verify(listener).onSetVoicemailArchiveStatus(false); + verifyQueries(); + } + + public void testSetVoicemailArchiveStatus_VoicemailExists() throws Throwable { + newVoicemailArchiveExistsUpdateQuery(true); + final OnSetVoicemailArchiveStatusListener listener = + mock(OnSetVoicemailArchiveStatusListener.class); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + mVoicemailAsyncTaskUtil.setVoicemailArchiveStatus(listener, + ARCHIVED_VOICEMAIL_URI, true); + } + }); + mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.SET_VOICEMAIL_ARCHIVE_STATUS); + verify(listener).onSetVoicemailArchiveStatus(true); + verifyQueries(); + } + + public void testArchiveVoicemailContent_ArchiveNotExists() throws Throwable { + newVoicemailArchiveExistsQuery().returnEmptyCursor(); + newQueryCallLogInfo().returnRow(getCallLogContentValues()); + newVoicemailQuery().returnRow(getVoicemailContentValues()); + newVoicemailArchiveInsert(); + final OnArchiveVoicemailListener listener = mock(OnArchiveVoicemailListener.class); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + mVoicemailAsyncTaskUtil.archiveVoicemailContent(listener, VOICEMAIL_URI); + } + }); + mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.ARCHIVE_VOICEMAIL_CONTENT); + verify(listener).onArchiveVoicemail(ARCHIVED_VOICEMAIL_URI); + verifyQueries(); + } + + public void testArchiveVoicemailContent_ArchiveExists() throws Throwable { + newVoicemailArchiveExistsQuery().returnRow(getCombinedValuesWithId()); + final OnArchiveVoicemailListener listener = mock(OnArchiveVoicemailListener.class); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + mVoicemailAsyncTaskUtil.archiveVoicemailContent(listener, VOICEMAIL_URI); + } + }); + mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.ARCHIVE_VOICEMAIL_CONTENT); + verify(listener).onArchiveVoicemail(ARCHIVED_VOICEMAIL_URI); + verifyQueries(); + } + + public void testArchiveVoicemailContent_CallLogInfoNotExists() throws Throwable { + newVoicemailArchiveExistsQuery().returnEmptyCursor(); + newQueryCallLogInfo().returnEmptyCursor(); + newVoicemailQuery().returnEmptyCursor(); + final OnArchiveVoicemailListener listener = mock(OnArchiveVoicemailListener.class); + runTestOnUiThread(new Runnable() { + @Override + public void run() { + mVoicemailAsyncTaskUtil.archiveVoicemailContent(listener, VOICEMAIL_URI); + } + }); + mFakeAsyncTaskExecutor.runTask(VoicemailAsyncTaskUtil.Tasks.ARCHIVE_VOICEMAIL_CONTENT); + verify(listener).onArchiveVoicemail(null); + verifyQueries(); + } + + private Query newVoicemailArchiveQuery() { + return mArchiveContentProvider.expectQuery(ARCHIVED_VOICEMAIL_URI); + } + + private Query newVoicemailArchiveFakeQuery() { + return mArchiveContentProvider.expectQuery(getFakeVoicemailUri()); + } + + private Query newQueryCallLogInfo() { + return mCallLogContentProvider.expectQuery(ContentUris.withAppendedId( + CallLog.Calls.CONTENT_URI_WITH_VOICEMAIL, ContentUris.parseId(VOICEMAIL_URI))) + .withProjection(CALLLOG_QUERY_PROJECTION); + } + + private Query newVoicemailQuery() { + return mVoicemailContentProvider.expectQuery(VOICEMAIL_URI).withAnySelection() + .withProjection(VOICEMAIL_PROJECTION); + } + + private Query newVoicemailArchiveExistsQuery() { + return mArchiveContentProvider.expectQuery( + VoicemailArchiveContract.VoicemailArchive.CONTENT_URI) + .withSelection(VoicemailArchiveContract.VoicemailArchive.SERVER_ID + "=" + + ContentUris.parseId(VOICEMAIL_URI), (String[]) null) + .withProjection(VoicemailArchiveContract.VoicemailArchive._ID); + } + + private void newVoicemailArchiveInsert() { + mArchiveContentProvider.expectInsert( + VoicemailArchiveContract.VoicemailArchive.CONTENT_URI, getCombinedContentValues(), + ARCHIVED_VOICEMAIL_URI); + } + + private void newVoicemailArchiveNotExistsUpdateQuery(boolean status) { + mArchiveContentProvider.expectUpdate(getFakeVoicemailUri(), + getArchiveStatusUpdateValues(status), null, null).returnRowsAffected(0); + } + + private void newVoicemailArchiveExistsUpdateQuery(boolean status) { + mArchiveContentProvider.expectUpdate(ARCHIVED_VOICEMAIL_URI, + getArchiveStatusUpdateValues(status), null, null).returnRowsAffected(1); + } + + private static ContentValues getCallLogContentValues() { + ContentValues values = new ContentValues(); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.GEOCODED_LOCATION], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_NAME], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.COUNTRY_ISO], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_NUMBER_TYPE], 0); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_NUMBER_LABEL], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_LOOKUP_URI], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_MATCHED_NUMBER], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_NORMALIZED_NUMBER], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.CACHED_FORMATTED_NUMBER], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.NUMBER_PRESENTATION], 0); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.ACCOUNT_COMPONENT_NAME], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.ACCOUNT_ID], ""); + values.put(CALLLOG_QUERY_PROJECTION[CallLogQuery.FEATURES], 0); + values.put(CALLLOG_QUERY_PROJECTION[23], ""); + return values; + } + + private static ContentValues getVoicemailContentValues() { + ContentValues values = new ContentValues(); + values.put(VoicemailContract.Voicemails.NUMBER, TEST_NUMBER); + values.put(VoicemailContract.Voicemails.DATE, TEST_DATE); + values.put(VoicemailContract.Voicemails.DURATION, TEST_DURATION); + values.put(VoicemailContract.Voicemails.MIME_TYPE, TEST_MIME_TYPE); + values.put(VoicemailContract.Voicemails._ID, TEST_SERVER_ID); + values.put(VoicemailContract.Voicemails.TRANSCRIPTION, TEST_TRANSCRIPTION); + values.put("_data", TEST_FILE_PATH); // VoicemailContract.Voicemails._DATA + return values; + } + + private static ContentValues getCombinedContentValues() { + ContentValues values = new ContentValues(); + // Call log info + values.put(VoicemailArchiveContract.VoicemailArchive.GEOCODED_LOCATION, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NAME, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_TYPE, 0); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NUMBER_LABEL, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_LOOKUP_URI, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_MATCHED_NUMBER, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_NORMALIZED_NUMBER, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_FORMATTED_NUMBER, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER_PRESENTATION, 0); + values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_COMPONENT_NAME, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.ACCOUNT_ID, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.FEATURES, 0); + values.put(VoicemailArchiveContract.VoicemailArchive.CACHED_PHOTO_URI, ""); + values.put(VoicemailArchiveContract.VoicemailArchive.COUNTRY_ISO, ""); + + // Voicemail content info + values.put(VoicemailArchiveContract.VoicemailArchive.NUMBER, TEST_NUMBER); + values.put(VoicemailArchiveContract.VoicemailArchive.DATE, TEST_DATE); + values.put(VoicemailArchiveContract.VoicemailArchive.DURATION, TEST_DURATION); + values.put(VoicemailArchiveContract.VoicemailArchive.MIME_TYPE, TEST_MIME_TYPE); + values.put(VoicemailArchiveContract.VoicemailArchive.SERVER_ID, TEST_SERVER_ID); + values.put(VoicemailArchiveContract.VoicemailArchive.TRANSCRIPTION, TEST_TRANSCRIPTION); + + // Custom fields + values.put(VoicemailArchiveContract.VoicemailArchive.ARCHIVED, false); + return values; + } + + private static ContentValues getCombinedContentValuesWithData() { + ContentValues values = getCombinedContentValues(); + values.put(VoicemailArchiveContract.VoicemailArchive._DATA, TEST_FILE_PATH); + return values; + } + + private static ContentValues getCombinedValuesWithId() { + ContentValues values = getCombinedContentValuesWithData(); + values.put(VoicemailArchiveContract.VoicemailArchive._ID, TEST_ID); + return values; + } + + private static ContentValues getArchiveStatusUpdateValues(boolean status) { + ContentValues values = new ContentValues(); + values.put(VoicemailArchiveContract.VoicemailArchive.ARCHIVED, status); + return values; + } + + private static Uri getFakeVoicemailUri() { + return VoicemailArchiveContract.VoicemailArchive.buildWithId(0); + } + + private void verifyQueries() { + mArchiveContentProvider.verify(); + mCallLogContentProvider.verify(); + mVoicemailContentProvider.verify(); + } + + private class TestVoicemailContentProvider extends MockContentProvider { + @Override + public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { + int modeBits = ParcelFileDescriptor.parseMode(mode); + try { + return ParcelFileDescriptor.open(mTemporaryFolder.newFile(), modeBits); + } catch (IOException e) { + return null; + } + } + + @Override + public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts) { + try { + return new AssetFileDescriptor(openFile(uri, "r"), 0, + AssetFileDescriptor.UNKNOWN_LENGTH); + } catch (FileNotFoundException e) { + return null; + } + } + } +} + -- cgit v1.2.3