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 getContentUri()66 protected abstract Uri getContentUri(); 67 getId()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") setUri(Uri uri)90 public T setUri(Uri uri) { 91 mUri = uri; 92 return (T)this; 93 } 94 getUri()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") with(String key, String value)104 public T with(String key, String value) { 105 mValues.put(key, value); 106 return (T)this; 107 } 108 109 @SuppressWarnings("unchecked") with(String key, long value)110 public T with(String key, long value) { 111 mValues.put(key, value); 112 return (T)this; 113 } 114 115 @SuppressWarnings("unchecked") with(String key, byte[] value)116 public T with(String key, byte[] value) { 117 mValues.put(key, value); 118 return (T)this; 119 } 120 121 @SuppressWarnings("unchecked") insert()122 public T insert() throws Exception { 123 insertDependent(); 124 mCreatedRows.add(this); 125 return (T)this; 126 } 127 128 @SuppressWarnings("unchecked") insertDependent()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 delete()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 deletePermanently()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") load()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") loadUsingValues()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 getLong(String columnName)197 public long getLong(String columnName) { 198 return mCursor.getLong(mCursor.getColumnIndex(columnName)); 199 } 200 getString(String columnName)201 public String getString(String columnName) { 202 return mCursor.getString(mCursor.getColumnIndex(columnName)); 203 } 204 assertColumn(String columnName, long value)205 public void assertColumn(String columnName, long value) { 206 assertEquals(value, mCursor.getLong(getColumnIndex(columnName))); 207 } 208 assertColumn(String columnName, String value)209 public void assertColumn(String columnName, String value) { 210 assertEquals(value, mCursor.getString(getColumnIndex(columnName))); 211 } 212 assertColumn(String columnName, byte[] value)213 public void assertColumn(String columnName, byte[] value) { 214 assertEquals(value, mCursor.getBlob(getColumnIndex(columnName))); 215 } 216 assertBlobColumnNotNull(String columnName)217 public void assertBlobColumnNotNull(String columnName) { 218 assertNotNull(mCursor.getBlob(getColumnIndex(columnName))); 219 } 220 assertBlobColumnNull(String columnName)221 public void assertBlobColumnNull(String columnName) { 222 assertNull(mCursor.getBlob(getColumnIndex(columnName))); 223 } 224 assertEquals(byte[] expected, byte[] actual)225 public void assertEquals(byte[] expected, byte[] actual) { 226 assertEquals(null, expected, actual); 227 } 228 assertEquals(String message, byte[] expected, byte[] actual)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 getColumnIndex(String columnName)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 close()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 getContentUri()260 protected Uri getContentUri() { 261 return RawContacts.CONTENT_URI; 262 } 263 newDataRow(String mimeType)264 public TestData newDataRow(String mimeType) { 265 return new TestData(this, mimeType); 266 } 267 getContactId()268 public long getContactId() { 269 return getLong(RawContacts.CONTACT_ID); 270 } 271 getContact()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 getContentUri()283 protected Uri getContentUri() { 284 return Contacts.CONTENT_URI; 285 } 286 } 287 288 private class NestedTestContact extends TestContact { 289 private final TestRawContact mRawContact; 290 NestedTestContact(TestRawContact rawContact)291 public NestedTestContact(TestRawContact rawContact) { 292 mRawContact = rawContact; 293 } 294 295 @Override getId()296 public long getId() throws Exception { 297 return mRawContact.getContactId(); 298 } 299 300 @Override load()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 getContentUri()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 TestData(TestRawContact rawContact, String mimeType)317 public TestData(TestRawContact rawContact, String mimeType) { 318 this.mRawContact = rawContact; 319 mValues.put(Data.MIMETYPE, mimeType); 320 } 321 322 @Override getContentUri()323 protected Uri getContentUri() { 324 return Data.CONTENT_URI; 325 } 326 327 @Override insert()328 public TestData insert() throws Exception { 329 mValues.put(Data.RAW_CONTACT_ID, mRawContact.getId()); 330 return super.insertDependent(); 331 } 332 getRawContactId()333 public long getRawContactId() { 334 return getLong(Data.RAW_CONTACT_ID); 335 } 336 getId()337 public long getId() { 338 return getLong(Data._ID); 339 } 340 getRawContact()341 public TestRawContact getRawContact() throws Exception { 342 return mRawContact; 343 } 344 } 345 ContactsContract_TestDataBuilder(ContentProviderClient provider)346 public ContactsContract_TestDataBuilder(ContentProviderClient provider) { 347 this.mProvider = provider; 348 } 349 newRawContact()350 public TestRawContact newRawContact() { 351 return new TestRawContact(); 352 } 353 newContact()354 public TestContact newContact() { 355 return new TestContact(); 356 } 357 newGroup()358 public TestGroup newGroup() { 359 return new TestGroup(); 360 } 361 cleanup()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