Home | History | Annotate | Download | only in contacts
      1 /*
      2  * Copyright (C) 2012 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.providers.contacts;
     18 
     19 import static com.android.providers.contacts.TestUtils.cv;
     20 
     21 import com.google.android.collect.Lists;
     22 
     23 import android.content.ContentProviderOperation;
     24 import android.content.ContentValues;
     25 import android.provider.ContactsContract;
     26 import android.provider.ContactsContract.CommonDataKinds.StructuredName;
     27 import android.provider.ContactsContract.Contacts;
     28 import android.provider.ContactsContract.Data;
     29 import android.provider.ContactsContract.Profile;
     30 import android.provider.ContactsContract.RawContacts;
     31 import android.test.suitebuilder.annotation.LargeTest;
     32 import android.util.Log;
     33 
     34 import java.util.ArrayList;
     35 
     36 /**
     37  * Tests to make sure we're handling DB transactions properly in regard to two databases,
     38  * the profile db and the contacts db.
     39  */
     40 @LargeTest
     41 public class ContactsProvider2TransactionTest extends BaseContactsProvider2Test {
     42     private SynchronousContactsProvider2 mProvider;
     43 
     44     @Override
     45     protected void setUp() throws Exception {
     46         super.setUp();
     47 
     48         mProvider = (SynchronousContactsProvider2) getProvider();
     49     }
     50 
     51     @Override
     52     protected void tearDown() throws Exception {
     53         super.tearDown();
     54 
     55         mProvider = null;
     56     }
     57 
     58     /**
     59      * Make sure we start/finish transactions on the right databases for insert.
     60      */
     61     public void testTransactionCallback_insert() {
     62 
     63         final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 86400);
     64 
     65         // Insert a raw contact.
     66         mProvider.resetTrasactionCallbackCalledFlags();
     67         mResolver.insert(RawContacts.CONTENT_URI, values);
     68 
     69         // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
     70         // profile db.
     71         mProvider.assertCommitTransactionCalledForContactMode();
     72         mProvider.assertNoTransactionsForProfileMode();
     73 
     74 
     75         // Insert a profile raw contact.
     76         mProvider.resetTrasactionCallbackCalledFlags();
     77         mResolver.insert(Profile.CONTENT_RAW_CONTACTS_URI, values);
     78 
     79         // Even though we only touched the profile DB, we also start and finish a transaction
     80         // on the contacts db.  AbstractContactsProvider does that to avoid deadlocks.
     81         mProvider.assertCommitTransactionCalledForContactMode();
     82         mProvider.assertCommitTransactionCalledForProfileMode();
     83     }
     84 
     85     /**
     86      * Make sure we start/finish transactions on the right databases for update.
     87      */
     88     public void testTransactionCallback_update() {
     89 
     90         final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 86400);
     91 
     92         // Make sure to create a raw contact and a profile raw contact.
     93         mResolver.insert(RawContacts.CONTENT_URI, values);
     94         mResolver.insert(Profile.CONTENT_RAW_CONTACTS_URI, values);
     95 
     96         values.clear();
     97         values.put(RawContacts.LAST_TIME_CONTACTED, 86400 * 2);
     98 
     99         // Update all raw contacts.
    100         mProvider.resetTrasactionCallbackCalledFlags();
    101         assertTrue(mResolver.update(RawContacts.CONTENT_URI, values, null, null) > 0);
    102 
    103         // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
    104         // profile db.
    105         mProvider.assertCommitTransactionCalledForContactMode();
    106         mProvider.assertNoTransactionsForProfileMode();
    107 
    108 
    109         // Update all profile raw contacts.
    110         mProvider.resetTrasactionCallbackCalledFlags();
    111         assertTrue(mResolver.update(Profile.CONTENT_RAW_CONTACTS_URI, values, null, null) > 0);
    112 
    113         // Even though we only touched the profile DB, we also start and finish a transaction
    114         // on the contacts db.  AbstractContactsProvider does that to avoid deadlocks.
    115         mProvider.assertCommitTransactionCalledForContactMode();
    116         mProvider.assertCommitTransactionCalledForProfileMode();
    117     }
    118 
    119     /**
    120      * Make sure we start/finish transactions on the right databases for delete.
    121      */
    122     public void testTransactionCallback_delete() {
    123 
    124         final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 86400);
    125 
    126         // Make sure to create a raw contact and a profile raw contact.
    127         mResolver.insert(RawContacts.CONTENT_URI, values);
    128         mResolver.insert(Profile.CONTENT_RAW_CONTACTS_URI, values);
    129 
    130         // Delete all raw contacts.
    131         mProvider.resetTrasactionCallbackCalledFlags();
    132         assertTrue(mResolver.delete(RawContacts.CONTENT_URI, null, null) > 0);
    133 
    134         // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
    135         // profile db.
    136         mProvider.assertCommitTransactionCalledForContactMode();
    137         mProvider.assertNoTransactionsForProfileMode();
    138 
    139         // Delete all profile raw contact.
    140         mProvider.resetTrasactionCallbackCalledFlags();
    141         assertTrue(mResolver.delete(Profile.CONTENT_RAW_CONTACTS_URI, null, null) > 0);
    142 
    143         // Even though we only touched the profile DB, we also start and finish a transaction
    144         // on the contacts db.  AbstractContactsProvider does that to avoid deadlocks.
    145         mProvider.assertCommitTransactionCalledForContactMode();
    146         mProvider.assertCommitTransactionCalledForProfileMode();
    147     }
    148     /**
    149      * Make sure we start/finish transactions on the right databases for bulk insert.
    150      */
    151     public void testTransactionCallback_bulkInsert() {
    152 
    153         final ContentValues values = cv(RawContacts.LAST_TIME_CONTACTED, 86400);
    154 
    155         // Insert a raw contact.
    156         mProvider.resetTrasactionCallbackCalledFlags();
    157         mResolver.bulkInsert(RawContacts.CONTENT_URI, new ContentValues[] {values});
    158 
    159         // Make sure we only COMMIT on the contacts DB, but there was no transaction on the
    160         // profile db.
    161         mProvider.assertCommitTransactionCalledForContactMode();
    162         mProvider.assertNoTransactionsForProfileMode();
    163 
    164 
    165         // Insert a profile raw contact.
    166         mProvider.resetTrasactionCallbackCalledFlags();
    167         mResolver.bulkInsert(Profile.CONTENT_RAW_CONTACTS_URI, new ContentValues[] {values});
    168 
    169         // Even though we only touched the profile DB, we also start and finish a transaction
    170         // on the contacts db.  AbstractContactsProvider does that to avoid deadlocks.
    171         mProvider.assertCommitTransactionCalledForContactMode();
    172         mProvider.assertCommitTransactionCalledForProfileMode();
    173     }
    174 
    175     /**
    176      * Add an operation to create a raw contact.
    177      */
    178     private static void addInsertContactOperations(ArrayList<ContentProviderOperation> ops) {
    179         ContentProviderOperation.Builder b;
    180         b = ContentProviderOperation.newInsert(RawContacts.CONTENT_URI);
    181         b.withValue(RawContacts.STARRED, 1);
    182         b.withValue(RawContacts.LAST_TIME_CONTACTED, 86400 * 21);
    183         ops.add(b.build());
    184 
    185         b = ContentProviderOperation.newInsert(Data.CONTENT_URI);
    186         b.withValueBackReference(Data.RAW_CONTACT_ID, ops.size() - 1);
    187         b.withValue(StructuredName.DISPLAY_NAME, "Regular Contact");
    188         b.withValue(StructuredName.GIVEN_NAME, "Regular");
    189         b.withValue(StructuredName.FAMILY_NAME, "Contact");
    190         b.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
    191         ops.add(b.build());
    192     }
    193 
    194     /**
    195      * Check for a contact created that'll be created for {@link #addInsertContactOperations}.
    196      */
    197     private void checkStoredContact() {
    198         assertStoredValues(Contacts.CONTENT_URI, cv(
    199                 Contacts.DISPLAY_NAME, "Regular Contact",
    200                 RawContacts.LAST_TIME_CONTACTED, 86400 * 21
    201                 ));
    202     }
    203 
    204     /**
    205      * Add an operation to create a profile raw contact.
    206      */
    207     private static void addInsertProfileOperations(ArrayList<ContentProviderOperation> ops) {
    208         ContentProviderOperation.Builder b;
    209         b = ContentProviderOperation.newInsert(Profile.CONTENT_RAW_CONTACTS_URI);
    210         b.withValue(RawContacts.STARRED, 1);
    211         b.withValue(RawContacts.LAST_TIME_CONTACTED, 86400 * 11);
    212         ops.add(b.build());
    213 
    214         b = ContentProviderOperation.newInsert(Data.CONTENT_URI);
    215         b.withValueBackReference(Data.RAW_CONTACT_ID, ops.size() - 1);
    216         b.withValue(StructuredName.DISPLAY_NAME, "Profile Contact");
    217         b.withValue(StructuredName.GIVEN_NAME, "Profile");
    218         b.withValue(StructuredName.FAMILY_NAME, "Contact");
    219         b.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
    220         ops.add(b.build());
    221     }
    222 
    223     /**
    224      * Check for a profile contact created that'll be created for
    225      * {@link #addInsertProfileOperations}.
    226      */
    227     private void checkStoredProfile() {
    228         assertStoredValues(Profile.CONTENT_URI, cv(
    229                 Contacts.DISPLAY_NAME, "Profile Contact",
    230                 RawContacts.LAST_TIME_CONTACTED, 86400 * 11
    231                 ));
    232     }
    233 
    234     public void testTransactionCallback_contactBatch() throws Exception {
    235         final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
    236 
    237         addInsertContactOperations(ops);
    238 
    239         mProvider.resetTrasactionCallbackCalledFlags();
    240 
    241         // Execute the operations.
    242         mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
    243 
    244         // Check the result
    245         mProvider.assertCommitTransactionCalledForContactMode();
    246         mProvider.assertNoTransactionsForProfileMode();
    247 
    248         checkStoredContact();
    249     }
    250 
    251     public void testTransactionCallback_profileBatch() throws Exception {
    252         final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
    253 
    254         addInsertProfileOperations(ops);
    255 
    256         mProvider.resetTrasactionCallbackCalledFlags();
    257 
    258         // Execute the operations.
    259         mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
    260 
    261         // Check the result
    262         mProvider.assertCommitTransactionCalledForContactMode();
    263         mProvider.assertCommitTransactionCalledForProfileMode();
    264 
    265         checkStoredProfile();
    266     }
    267 
    268     public void testTransactionCallback_mixedBatch() throws Exception {
    269         final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
    270 
    271         // Create a raw contact and a profile raw contact in a single batch.
    272 
    273         addInsertContactOperations(ops);
    274         addInsertProfileOperations(ops);
    275 
    276         mProvider.resetTrasactionCallbackCalledFlags();
    277 
    278         // Execute the operations.
    279         mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
    280 
    281         // Check the result
    282         mProvider.assertCommitTransactionCalledForContactMode();
    283         mProvider.assertCommitTransactionCalledForProfileMode();
    284 
    285         checkStoredProfile();
    286         checkStoredContact();
    287     }
    288 
    289     public void testTransactionCallback_mixedBatchReversed() throws Exception {
    290         final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
    291 
    292         // Create a profile raw contact and a raw contact in a single batch.
    293 
    294         addInsertProfileOperations(ops);
    295         addInsertContactOperations(ops);
    296 
    297         mProvider.resetTrasactionCallbackCalledFlags();
    298 
    299         // Execute the operations.
    300         mResolver.applyBatch(ContactsContract.AUTHORITY, ops);
    301 
    302         // Check the result
    303         mProvider.assertCommitTransactionCalledForContactMode();
    304         mProvider.assertCommitTransactionCalledForProfileMode();
    305 
    306         checkStoredProfile();
    307         checkStoredContact();
    308     }
    309 }
    310