Home | History | Annotate | Download | only in contacts
      1 /*
      2  * Copyright (C) 2010 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 android.provider.cts.contacts;
     18 
     19 import com.google.android.collect.Lists;
     20 import com.google.android.collect.Sets;
     21 
     22 import android.content.ContentProviderClient;
     23 import android.content.ContentUris;
     24 import android.content.ContentValues;
     25 import android.database.Cursor;
     26 import android.net.Uri;
     27 import android.provider.BaseColumns;
     28 import android.provider.ContactsContract;
     29 import android.provider.ContactsContract.Contacts;
     30 import android.provider.ContactsContract.Data;
     31 import android.provider.ContactsContract.Groups;
     32 import android.provider.ContactsContract.RawContacts;
     33 import android.text.TextUtils;
     34 
     35 import java.util.ArrayList;
     36 import java.util.Arrays;
     37 import java.util.HashSet;
     38 import java.util.Map;
     39 import java.util.Set;
     40 
     41 import junit.framework.Assert;
     42 import junit.framework.ComparisonFailure;
     43 
     44 /**
     45  * A test data builder for ContactsContract tests.
     46  */
     47 public class ContactsContract_TestDataBuilder {
     48     private ContentProviderClient mProvider;
     49     private ArrayList<Builder<?>> mCreatedRows = Lists.newArrayList();
     50     private HashSet<Builder<?>> mLoadedRows = Sets.newHashSet();
     51 
     52     private interface IdQuery {
     53         String[] COLUMNS = new String[] {
     54             BaseColumns._ID,
     55         };
     56 
     57         int _ID = 0;
     58     }
     59 
     60     public abstract class  Builder<T extends Builder<?>> extends Assert {
     61         protected ContentValues mValues = new ContentValues();
     62         private Uri mUri;
     63         private long mId = -1;
     64         private Cursor mCursor;
     65         private boolean mAlreadyDeleted;
     66 
     67         protected abstract Uri getContentUri();
     68 
     69         public long getId() throws Exception {
     70             if (mId != -1) {
     71                 return mId;
     72             }
     73 
     74             assertNotNull("Row has not be inserted or loaded yet", mUri);
     75 
     76             Cursor cursor = mProvider.query(mUri, IdQuery.COLUMNS, null, null, null, null);
     77             if (cursor != null) {
     78                 try {
     79                     cursor.moveToFirst();
     80                     mId = cursor.getInt(IdQuery._ID);
     81                 } finally {
     82                     cursor.close();
     83                 }
     84 
     85             }
     86             assertTrue("Could not obtain _ID for URI: " + mUri, mId != -1);
     87             return mId;
     88         }
     89 
     90         @SuppressWarnings("unchecked")
     91         public T setUri(Uri uri) {
     92             mUri = uri;
     93             return (T)this;
     94         }
     95 
     96         public Uri getUri() {
     97             if (mUri == null) {
     98                 assertTrue("Neither URI nor ID has been specified", mId != -1);
     99                 mUri = ContentUris.withAppendedId(getContentUri(), mId);
    100             }
    101             return mUri;
    102         }
    103 
    104         @SuppressWarnings("unchecked")
    105         public T with(String key, String value) {
    106             mValues.put(key, value);
    107             return (T)this;
    108         }
    109 
    110         @SuppressWarnings("unchecked")
    111         public T with(String key, long value) {
    112             mValues.put(key, value);
    113             return (T)this;
    114         }
    115 
    116         @SuppressWarnings("unchecked")
    117         public T with(String key, byte[] value) {
    118             mValues.put(key, value);
    119             return (T)this;
    120         }
    121 
    122         @SuppressWarnings("unchecked")
    123         public T insert() throws Exception {
    124             insertDependent();
    125             mCreatedRows.add(this);
    126             return (T)this;
    127         }
    128 
    129         @SuppressWarnings("unchecked")
    130         public T insertDependent() throws Exception {
    131             mUri = mProvider.insert(getContentUri(), mValues);
    132             assertNotNull("Could not insert a row in " + getContentUri(), mUri);
    133             mId = ContentUris.parseId(mUri);
    134             return (T)this;
    135         }
    136 
    137         public void delete() throws Exception {
    138             int count = mProvider.delete(getUri(), null, null);
    139             assertEquals("Wrong number of rows deleted for " + getUri(), 1, count);
    140         }
    141 
    142         public void deletePermanently() throws Exception {
    143             if (mAlreadyDeleted) {
    144                 return;
    145             }
    146             Uri uri = getUri().buildUpon()
    147                     .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
    148                     .build();
    149             int count = mProvider.delete(uri, null, null);
    150             assertEquals("Wrong number of rows deleted for " + uri, 1, count);
    151             mCreatedRows.remove(this);
    152         }
    153 
    154         @SuppressWarnings("unchecked")
    155         public T load() throws Exception {
    156             close();
    157             mLoadedRows.add(this);
    158 
    159             mCursor = mProvider.query(getUri(), null, null, null, null, null);
    160             if (mCursor == null || !mCursor.moveToFirst()) {
    161                 return null;
    162             } else {
    163                 return (T) this;
    164             }
    165         }
    166 
    167         @SuppressWarnings("unchecked")
    168         public T loadUsingValues() throws Exception {
    169             close();
    170             mLoadedRows.add(this);
    171 
    172             StringBuilder selection = new StringBuilder();
    173             ArrayList<String> selectionArgs = Lists.newArrayList();
    174             Set<Map.Entry<String, Object>> entries = mValues.valueSet();
    175             for (Map.Entry<String, Object> entry : entries) {
    176                 String column = entry.getKey();
    177                 Object value = entry.getValue();
    178 
    179                 if (selection.length() != 0) {
    180                     selection.append(" AND ");
    181                 }
    182 
    183                 selection.append(column);
    184                 if (value == null) {
    185                     selection.append(" NOT NULL");
    186                 } else {
    187                     selection.append("=?");
    188                     selectionArgs.add(value.toString());
    189                 }
    190             }
    191             mCursor = mProvider.query(getContentUri(), null,
    192                     selection.toString(),
    193                     selectionArgs.toArray(new String[0]), null, null);
    194             if (mCursor == null || !mCursor.moveToFirst()) {
    195                 fail("No data rows for " + getContentUri() + "[" + mValues.toString() + "]");
    196             }
    197             mId = mCursor.getLong(getColumnIndex(BaseColumns._ID));
    198             return (T)this;
    199         }
    200 
    201         public boolean isNull(String columnName) {
    202             return mCursor.isNull(mCursor.getColumnIndex(columnName));
    203         }
    204 
    205         public long getLong(String columnName) {
    206             return mCursor.getLong(mCursor.getColumnIndex(columnName));
    207         }
    208 
    209         public String getString(String columnName) {
    210             return mCursor.getString(mCursor.getColumnIndex(columnName));
    211         }
    212 
    213         public void assertColumn(String columnName, long value) {
    214             assertEquals(value, mCursor.getLong(getColumnIndex(columnName)));
    215         }
    216 
    217         public void assertColumn(String columnName, String value) {
    218             assertEquals(value, mCursor.getString(getColumnIndex(columnName)));
    219         }
    220 
    221         public void assertColumn(String columnName, byte[] value) {
    222             assertEquals(value, mCursor.getBlob(getColumnIndex(columnName)));
    223         }
    224 
    225         public void assertBlobColumnNotNull(String columnName) {
    226             assertNotNull(mCursor.getBlob(getColumnIndex(columnName)));
    227         }
    228 
    229         public void assertBlobColumnNull(String columnName) {
    230             assertNull(mCursor.getBlob(getColumnIndex(columnName)));
    231         }
    232 
    233         public void assertEquals(byte[] expected, byte[] actual) {
    234             assertEquals(null, expected, actual);
    235         }
    236 
    237         public void assertEquals(String message, byte[] expected, byte[] actual) {
    238             if (expected == null && actual == null)
    239                 return;
    240             if (expected != null && Arrays.equals(actual, expected))
    241                 return;
    242             throw new ComparisonFailure(message, expected.toString(), actual.toString());
    243         }
    244 
    245         private int getColumnIndex(String columnName) {
    246             int index = mCursor.getColumnIndex(columnName);
    247             assertTrue("No such column: " + columnName +
    248                     ". Available columns: " + TextUtils.join(", ", mCursor.getColumnNames()),
    249                     index != -1);
    250             return index;
    251         }
    252 
    253         public void close() {
    254             if (mCursor != null) {
    255                 mCursor.close();
    256                 mCursor = null;
    257             }
    258             mLoadedRows.remove(this);
    259         }
    260 
    261         public void setAlreadyDeleted() {
    262             mAlreadyDeleted = true;
    263         }
    264     }
    265 
    266     public class TestRawContact extends Builder<TestRawContact> {
    267 
    268         private TestContact mContact;
    269 
    270         @Override
    271         protected Uri getContentUri() {
    272             return RawContacts.CONTENT_URI;
    273         }
    274 
    275         public TestData newDataRow(String mimeType) {
    276             return new TestData(this, mimeType);
    277         }
    278 
    279         public long getContactId() {
    280             return getLong(RawContacts.CONTACT_ID);
    281         }
    282 
    283         public TestContact getContact() throws Exception {
    284             if (mContact == null) {
    285                 mContact = new NestedTestContact(this);
    286             }
    287             return mContact;
    288         }
    289     }
    290 
    291     public class TestContact extends Builder<TestContact> {
    292 
    293         @Override
    294         protected Uri getContentUri() {
    295             return Contacts.CONTENT_URI;
    296         }
    297     }
    298 
    299     private class NestedTestContact extends TestContact {
    300         private final TestRawContact mRawContact;
    301 
    302         public NestedTestContact(TestRawContact rawContact) {
    303             mRawContact = rawContact;
    304         }
    305 
    306         @Override
    307         public long getId() throws Exception {
    308             return mRawContact.getContactId();
    309         }
    310 
    311         @Override
    312         public TestContact load() throws Exception {
    313             return with(Contacts._ID, mRawContact.getContactId()).loadUsingValues();
    314         }
    315     }
    316 
    317     public class TestGroup extends Builder<TestGroup> {
    318 
    319         @Override
    320         protected Uri getContentUri() {
    321             return Groups.CONTENT_URI;
    322         }
    323     }
    324 
    325     public class TestData extends Builder<TestData> {
    326         private final TestRawContact mRawContact;
    327 
    328         public TestData(TestRawContact rawContact, String mimeType) {
    329             this.mRawContact = rawContact;
    330             mValues.put(Data.MIMETYPE, mimeType);
    331         }
    332 
    333         @Override
    334         protected Uri getContentUri() {
    335             return Data.CONTENT_URI;
    336         }
    337 
    338         @Override
    339         public TestData insert() throws Exception {
    340             mValues.put(Data.RAW_CONTACT_ID, mRawContact.getId());
    341             return super.insertDependent();
    342         }
    343 
    344         public long getRawContactId() {
    345             return getLong(Data.RAW_CONTACT_ID);
    346         }
    347 
    348         public long getId() {
    349             return getLong(Data._ID);
    350         }
    351 
    352         public TestRawContact getRawContact() throws Exception {
    353             return mRawContact;
    354         }
    355     }
    356 
    357     public ContactsContract_TestDataBuilder(ContentProviderClient provider) {
    358         this.mProvider = provider;
    359     }
    360 
    361     public TestRawContact newRawContact() {
    362         return new TestRawContact();
    363     }
    364 
    365     public TestContact newContact() {
    366         return new TestContact();
    367     }
    368 
    369     public TestGroup newGroup() {
    370         return new TestGroup();
    371     }
    372 
    373     public void cleanup() throws Exception {
    374         for (Builder<?> builder : new ArrayList<Builder<?>>(mCreatedRows)) {
    375             builder.deletePermanently();
    376         }
    377 
    378         for (Builder<?> builder : new HashSet<Builder<?>>(mLoadedRows)) {
    379             builder.close();
    380         }
    381     }
    382 
    383 }
    384