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