Home | History | Annotate | Download | only in datamodel
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.messaging.datamodel;
     18 
     19 import android.content.ContentProvider;
     20 import android.content.ContentValues;
     21 import android.database.Cursor;
     22 import android.net.Uri;
     23 import android.test.suitebuilder.annotation.SmallTest;
     24 import android.text.TextUtils;
     25 
     26 import com.android.messaging.BugleTestCase;
     27 import com.android.messaging.FakeContentProvider;
     28 import com.android.messaging.FakeContext;
     29 import com.android.messaging.FakeFactory;
     30 import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
     31 import com.android.messaging.datamodel.data.ParticipantData;
     32 import com.android.messaging.datamodel.data.ParticipantData.ParticipantsQuery;
     33 import com.android.messaging.util.ContactUtil;
     34 
     35 import org.junit.Assert;
     36 
     37 /**
     38  * Utility class for testing ParticipantRefresh class for different scenarios.
     39  */
     40 @SmallTest
     41 public class ParticipantRefreshTest extends BugleTestCase {
     42     private FakeContext mContext;
     43     FakeFactory mFakeFactory;
     44 
     45     @Override
     46     public void setUp() throws Exception {
     47         super.setUp();
     48 
     49         mContext = new FakeContext(getTestContext());
     50 
     51         final ContentProvider provider = new MessagingContentProvider();
     52         provider.attachInfo(mContext, null);
     53         mContext.addContentProvider(MessagingContentProvider.AUTHORITY, provider);
     54 
     55         final FakeDataModel fakeDataModel = new FakeDataModel(mContext);
     56         mFakeFactory = FakeFactory.registerWithFakeContext(getTestContext(), mContext)
     57                 .withDataModel(fakeDataModel);
     58     }
     59 
     60     /**
     61      * Add some phonelookup result into take PhoneLookup content provider. This will be
     62      * used for doing phone lookup during participant refresh.
     63      */
     64     private void addPhoneLookup(final String phone, final Object[][] lookupResult) {
     65         final Uri uri = ContactUtil.lookupPhone(mContext, phone).getUri();
     66         final FakeContentProvider phoneLookup = new FakeContentProvider(mContext,
     67                 uri, false);
     68         phoneLookup.addOverrideData(uri, null, null, ContactUtil.PhoneLookupQuery.PROJECTION,
     69                 lookupResult);
     70         mFakeFactory.withProvider(uri, phoneLookup);
     71     }
     72 
     73     /**
     74      * Add some participant to test database.
     75      */
     76     private void addParticipant(final String normalizedDestination, final long contactId,
     77             final String name, final String photoUrl) {
     78         final DatabaseWrapper db = DataModel.get().getDatabase();
     79         final ContentValues values = new ContentValues();
     80 
     81         values.put(ParticipantColumns.NORMALIZED_DESTINATION, normalizedDestination);
     82         values.put(ParticipantColumns.CONTACT_ID, contactId);
     83         values.put(ParticipantColumns.FULL_NAME, name);
     84         values.put(ParticipantColumns.PROFILE_PHOTO_URI, photoUrl);
     85 
     86         db.beginTransaction();
     87         try {
     88             db.insert(DatabaseHelper.PARTICIPANTS_TABLE, null, values);
     89             db.setTransactionSuccessful();
     90         } finally {
     91             db.endTransaction();
     92         }
     93     }
     94 
     95     /**
     96      * Verify that participant in the database has expected contacdtId, name and photoUrl fields.
     97      */
     98     private void verifyParticipant(final String normalizedDestination, final long contactId,
     99             final String name, final String photoUrl) {
    100         final DatabaseWrapper db = DataModel.get().getDatabase();
    101         db.beginTransaction();
    102         try {
    103             final String selection = ParticipantColumns.NORMALIZED_DESTINATION + "=?";
    104             final String[] selectionArgs = new String[] { normalizedDestination };
    105 
    106             final Cursor cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
    107                     ParticipantsQuery.PROJECTION, selection, selectionArgs, null, null, null);
    108 
    109             if (cursor == null || cursor.getCount() != 1) {
    110                 Assert.fail("Should have participants for:" + normalizedDestination);
    111                 return;
    112             }
    113 
    114             cursor.moveToFirst();
    115             final int currentContactId = cursor.getInt(ParticipantsQuery.INDEX_CONTACT_ID);
    116             final String currentName = cursor.getString(ParticipantsQuery.INDEX_FULL_NAME);
    117             final String currentPhotoUrl =
    118                     cursor.getString(ParticipantsQuery.INDEX_PROFILE_PHOTO_URI);
    119             if (currentContactId != contactId) {
    120                 Assert.fail("Contact Id doesn't match. normalizedNumber=" + normalizedDestination +
    121                         " expected=" + contactId + " actual=" + currentContactId);
    122                 return;
    123             }
    124 
    125             if (!TextUtils.equals(currentName, name)) {
    126                 Assert.fail("Name doesn't match. normalizedNumber=" + normalizedDestination +
    127                         " expected=" + name + " actual=" + currentName);
    128                 return;
    129             }
    130 
    131             if (!TextUtils.equals(currentPhotoUrl, photoUrl)) {
    132                 Assert.fail("Contact Id doesn't match. normalizedNumber=" + normalizedDestination +
    133                         " expected=" + photoUrl + " actual=" + currentPhotoUrl);
    134                 return;
    135             }
    136 
    137             db.setTransactionSuccessful();
    138         } finally {
    139             db.endTransaction();
    140         }
    141     }
    142 
    143     /**
    144      * Verify that incremental refresh will resolve previously not resolved participants.
    145      */
    146     public void testIncrementalRefreshNotResolvedSingleMatch() {
    147         addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED,
    148                 null, null);
    149         addPhoneLookup("650-123-1233", new Object[][] {
    150                 { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
    151         });
    152 
    153         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
    154         verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
    155     }
    156 
    157     /**
    158      * Verify that incremental refresh will resolve previously not resolved participants.
    159      */
    160     public void testIncrementalRefreshNotResolvedMultiMatch() {
    161         addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED,
    162                 null, null);
    163         addPhoneLookup("650-123-1233", new Object[][] {
    164                 { 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
    165                 { 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
    166         });
    167 
    168         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
    169         verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
    170     }
    171 
    172     /**
    173      * Verify that incremental refresh will not touch already-resolved participants.
    174      */
    175     public void testIncrementalRefreshResolvedSingleMatch() {
    176         addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
    177         addPhoneLookup("650-123-1233", new Object[][] {
    178                 { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
    179         });
    180 
    181         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
    182         verifyParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
    183     }
    184 
    185     /**
    186      * Verify that full refresh will correct already-resolved participants if needed
    187      */
    188     public void testFullRefreshResolvedSingleMatch() {
    189         addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
    190         addPhoneLookup("650-123-1233", new Object[][] {
    191                 { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
    192         });
    193 
    194         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
    195         verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
    196     }
    197 
    198     /**
    199      * Verify that incremental refresh will not touch participant that is marked as not found.
    200      */
    201     public void testIncrementalRefreshNotFound() {
    202         addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
    203                 null, null);
    204         addPhoneLookup("650-123-1233", new Object[][] {
    205                 { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
    206         });
    207 
    208         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_INCREMENTAL);
    209         verifyParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
    210                 null, null);
    211     }
    212 
    213     /**
    214      * Verify that full refresh will resolve participant that is marked as not found.
    215      */
    216     public void testFullRefreshNotFound() {
    217         addParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
    218                 null, null);
    219         addPhoneLookup("650-123-1233", new Object[][] {
    220                 { 1L, "John", "content://photo/john", "650-123-1233", null, null, null }
    221         });
    222 
    223         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
    224         verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
    225     }
    226 
    227     /**
    228      * Verify that refresh take consideration of current contact_id when having multiple matches.
    229      */
    230     public void testFullRefreshResolvedMultiMatch1() {
    231         addParticipant("650-123-1233", 1, "Joh", "content://photo/joh");
    232         addPhoneLookup("650-123-1233", new Object[][] {
    233                 { 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
    234                 { 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
    235         });
    236 
    237         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
    238         verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
    239     }
    240 
    241     /**
    242      * Verify that refresh take consideration of current contact_id when having multiple matches.
    243      */
    244     public void testFullRefreshResolvedMultiMatch2() {
    245         addParticipant("650-123-1233", 2, "Joh", "content://photo/joh");
    246         addPhoneLookup("650-123-1233", new Object[][] {
    247                 { 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
    248                 { 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
    249         });
    250 
    251         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
    252         verifyParticipant("650-123-1233", 2, "Joe", "content://photo/joe");
    253     }
    254 
    255     /**
    256      * Verify that refresh take first contact in case current contact_id no longer matches.
    257      */
    258     public void testFullRefreshResolvedMultiMatch3() {
    259         addParticipant("650-123-1233", 3, "Joh", "content://photo/joh");
    260         addPhoneLookup("650-123-1233", new Object[][] {
    261                 { 1L, "John", "content://photo/john", "650-123-1233", null, null, null },
    262                 { 2L, "Joe", "content://photo/joe", "650-123-1233", null, null, null }
    263         });
    264 
    265         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
    266         verifyParticipant("650-123-1233", 1, "John", "content://photo/john");
    267     }
    268 
    269     /**
    270      * Verify that refresh take first contact in case current contact_id no longer matches.
    271      */
    272     public void testFullRefreshResolvedBeforeButNotFoundNow() {
    273         addParticipant("650-123-1233", 3, "Joh", "content://photo/joh");
    274         addPhoneLookup("650-123-1233", new Object[][] {});
    275 
    276         ParticipantRefresh.refreshParticipants(ParticipantRefresh.REFRESH_MODE_FULL);
    277         verifyParticipant("650-123-1233", ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND,
    278                 null, null);
    279     }
    280 }
    281