1package com.xtremelabs.robolectric.shadows; 2 3import static android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI; 4import static com.xtremelabs.robolectric.Robolectric.shadowOf; 5import static org.hamcrest.CoreMatchers.equalTo; 6import static org.hamcrest.CoreMatchers.hasItem; 7import static org.hamcrest.CoreMatchers.is; 8import static org.hamcrest.CoreMatchers.notNullValue; 9import static org.hamcrest.CoreMatchers.nullValue; 10import static org.hamcrest.CoreMatchers.sameInstance; 11import static org.junit.Assert.*; 12 13import java.io.InputStream; 14import java.io.OutputStream; 15import java.util.ArrayList; 16import java.util.List; 17 18import android.accounts.Account; 19import android.content.*; 20import android.os.Bundle; 21import org.hamcrest.CoreMatchers; 22import org.junit.Before; 23import org.junit.Test; 24import org.junit.runner.RunWith; 25 26import android.app.Activity; 27import android.database.Cursor; 28import android.net.Uri; 29import android.os.RemoteException; 30 31import com.xtremelabs.robolectric.WithTestDefaultsRunner; 32import com.xtremelabs.robolectric.tester.android.database.TestCursor; 33 34@RunWith(WithTestDefaultsRunner.class) 35public class ContentResolverTest { 36 static final String AUTHORITY = "com.xtremelabs.robolectric"; 37 38 private ContentResolver contentResolver; 39 private ShadowContentResolver shadowContentResolver; 40 private Uri uri21; 41 private Uri uri22; 42 private Account a, b; 43 44 @Before 45 public void setUp() throws Exception { 46 contentResolver = new Activity().getContentResolver(); 47 shadowContentResolver = shadowOf(contentResolver); 48 uri21 = Uri.parse(EXTERNAL_CONTENT_URI.toString() + "/21"); 49 uri22 = Uri.parse(EXTERNAL_CONTENT_URI.toString() + "/22"); 50 51 a = new Account("a", "type"); 52 b = new Account("b", "type"); 53 } 54 55 @Test 56 public void insert_shouldReturnIncreasingUris() throws Exception { 57 shadowContentResolver.setNextDatabaseIdForInserts(21); 58 59 assertThat(contentResolver.insert(EXTERNAL_CONTENT_URI, new ContentValues()), equalTo(uri21)); 60 assertThat(contentResolver.insert(EXTERNAL_CONTENT_URI, new ContentValues()), equalTo(uri22)); 61 } 62 63 @Test 64 public void insert_shouldTrackInsertStatements() throws Exception { 65 ContentValues contentValues = new ContentValues(); 66 contentValues.put("foo", "bar"); 67 contentResolver.insert(EXTERNAL_CONTENT_URI, contentValues); 68 assertThat(shadowContentResolver.getInsertStatements().size(), is(1)); 69 assertThat(shadowContentResolver.getInsertStatements().get(0).getUri(), equalTo(EXTERNAL_CONTENT_URI)); 70 assertThat(shadowContentResolver.getInsertStatements().get(0).getContentValues().getAsString("foo"), equalTo("bar")); 71 72 contentValues = new ContentValues(); 73 contentValues.put("hello", "world"); 74 contentResolver.insert(EXTERNAL_CONTENT_URI, contentValues); 75 assertThat(shadowContentResolver.getInsertStatements().size(), is(2)); 76 assertThat(shadowContentResolver.getInsertStatements().get(1).getContentValues().getAsString("hello"), equalTo("world")); 77 } 78 79 @Test 80 public void insert_shouldTrackUpdateStatements() throws Exception { 81 ContentValues contentValues = new ContentValues(); 82 contentValues.put("foo", "bar"); 83 contentResolver.update(EXTERNAL_CONTENT_URI, contentValues, "robolectric", new String[] { "awesome" }); 84 assertThat(shadowContentResolver.getUpdateStatements().size(), is(1)); 85 assertThat(shadowContentResolver.getUpdateStatements().get(0).getUri(), equalTo(EXTERNAL_CONTENT_URI)); 86 assertThat(shadowContentResolver.getUpdateStatements().get(0).getContentValues().getAsString("foo"), equalTo("bar")); 87 assertThat(shadowContentResolver.getUpdateStatements().get(0).getWhere(), equalTo("robolectric")); 88 assertThat(shadowContentResolver.getUpdateStatements().get(0).getSelectionArgs(), equalTo(new String[] { "awesome" })); 89 90 contentValues = new ContentValues(); 91 contentValues.put("hello", "world"); 92 contentResolver.update(EXTERNAL_CONTENT_URI, contentValues, null, null); 93 assertThat(shadowContentResolver.getUpdateStatements().size(), is(2)); 94 assertThat(shadowContentResolver.getUpdateStatements().get(1).getUri(), equalTo(EXTERNAL_CONTENT_URI)); 95 assertThat(shadowContentResolver.getUpdateStatements().get(1).getContentValues().getAsString("hello"), equalTo("world")); 96 assertThat(shadowContentResolver.getUpdateStatements().get(1).getWhere(), nullValue()); 97 assertThat(shadowContentResolver.getUpdateStatements().get(1).getSelectionArgs(), nullValue()); 98 } 99 100 @Test 101 public void delete_shouldTrackDeletedUris() throws Exception { 102 assertThat(shadowContentResolver.getDeletedUris().size(), equalTo(0)); 103 104 assertThat(contentResolver.delete(uri21, null, null), equalTo(1)); 105 assertThat(shadowContentResolver.getDeletedUris(), hasItem(uri21)); 106 assertThat(shadowContentResolver.getDeletedUris().size(), equalTo(1)); 107 108 assertThat(contentResolver.delete(uri22, null, null), equalTo(1)); 109 assertThat(shadowContentResolver.getDeletedUris(), hasItem(uri22)); 110 assertThat(shadowContentResolver.getDeletedUris().size(), equalTo(2)); 111 } 112 113 @Test 114 public void delete_shouldTrackDeletedStatements() { 115 assertThat(shadowContentResolver.getDeleteStatements().size(), equalTo(0)); 116 117 assertThat(contentResolver.delete(uri21, "id", new String[] { "5" }), equalTo(1)); 118 assertThat(shadowContentResolver.getDeleteStatements().size(), equalTo(1)); 119 assertThat(shadowContentResolver.getDeleteStatements().get(0).getUri(), equalTo(uri21)); 120 assertThat(shadowContentResolver.getDeleteStatements().get(0).getWhere(), equalTo("id")); 121 assertThat(shadowContentResolver.getDeleteStatements().get(0).getSelectionArgs()[0], equalTo("5")); 122 123 assertThat(contentResolver.delete(uri21, "foo", new String[] { "bar" }), equalTo(1)); 124 assertThat(shadowContentResolver.getDeleteStatements().size(), equalTo(2)); 125 assertThat(shadowContentResolver.getDeleteStatements().get(1).getUri(), equalTo(uri21)); 126 assertThat(shadowContentResolver.getDeleteStatements().get(1).getWhere(), equalTo("foo")); 127 assertThat(shadowContentResolver.getDeleteStatements().get(1).getSelectionArgs()[0], equalTo("bar")); 128 } 129 130 @Test 131 public void query_shouldReturnTheCursorThatWasSet() throws Exception { 132 assertNull(shadowContentResolver.query(null, null, null, null, null)); 133 TestCursor cursor = new TestCursor(); 134 shadowContentResolver.setCursor(cursor); 135 assertThat((TestCursor) shadowContentResolver.query(null, null, null, null, null), 136 sameInstance(cursor)); 137 } 138 139 @Test 140 public void query__shouldReturnSpecificCursorsForSpecificUris() throws Exception { 141 assertNull(shadowContentResolver.query(uri21, null, null, null, null)); 142 assertNull(shadowContentResolver.query(uri22, null, null, null, null)); 143 144 TestCursor cursor21 = new TestCursor(); 145 TestCursor cursor22 = new TestCursor(); 146 shadowContentResolver.setCursor(uri21, cursor21); 147 shadowContentResolver.setCursor(uri22, cursor22); 148 149 assertThat((TestCursor) shadowContentResolver.query(uri21, null, null, null, null), 150 sameInstance(cursor21)); 151 assertThat((TestCursor) shadowContentResolver.query(uri22, null, null, null, null), 152 sameInstance(cursor22)); 153 } 154 155 @Test 156 public void query__shouldKnowWhatItsParamsWere() throws Exception { 157 String[] projection = {}; 158 String selection = "select"; 159 String[] selectionArgs = {}; 160 String sortOrder = "order"; 161 162 QueryParamTrackingTestCursor testCursor = new QueryParamTrackingTestCursor(); 163 164 shadowContentResolver.setCursor(testCursor); 165 Cursor cursor = shadowContentResolver.query(uri21, projection, selection, selectionArgs, sortOrder); 166 assertThat((QueryParamTrackingTestCursor)cursor, equalTo(testCursor)); 167 assertThat(testCursor.uri, equalTo(uri21)); 168 assertThat(testCursor.projection, equalTo(projection)); 169 assertThat(testCursor.selection, equalTo(selection)); 170 assertThat(testCursor.selectionArgs, equalTo(selectionArgs)); 171 assertThat(testCursor.sortOrder, equalTo(sortOrder)); 172 } 173 174 @Test 175 public void openInputStream_shouldReturnAnInputStream() throws Exception { 176 assertThat(contentResolver.openInputStream(uri21), CoreMatchers.instanceOf(InputStream.class)); 177 } 178 179 @Test 180 public void openOutputStream_shouldReturnAnOutputStream() throws Exception { 181 assertThat(contentResolver.openOutputStream(uri21), CoreMatchers.instanceOf(OutputStream.class)); 182 } 183 184 @Test 185 public void shouldTrackNotifiedUris() throws Exception { 186 contentResolver.notifyChange(Uri.parse("foo"), null, true); 187 contentResolver.notifyChange(Uri.parse("bar"), null); 188 189 assertThat(shadowContentResolver.getNotifiedUris().size(), equalTo(2)); 190 ShadowContentResolver.NotifiedUri uri = shadowContentResolver.getNotifiedUris().get(0); 191 192 assertThat(uri.uri.toString(), equalTo("foo")); 193 assertTrue(uri.syncToNetwork); 194 assertNull(uri.observer); 195 196 uri = shadowContentResolver.getNotifiedUris().get(1); 197 198 assertThat(uri.uri.toString(), equalTo("bar")); 199 assertFalse(uri.syncToNetwork); 200 assertNull(uri.observer); 201 } 202 203 @Test 204 public void applyBatch() throws RemoteException, OperationApplicationException { 205 ArrayList<ContentProviderOperation> resultOperations = shadowContentResolver.getContentProviderOperations(AUTHORITY); 206 assertThat(resultOperations, notNullValue()); 207 assertThat(resultOperations.size(), is(0)); 208 209 ContentProviderResult[] contentProviderResults = new ContentProviderResult[] { 210 new ContentProviderResult(1), 211 new ContentProviderResult(1), 212 }; 213 shadowContentResolver.setContentProviderResult(contentProviderResults); 214 Uri uri = Uri.parse("content://com.xtremelabs.robolectric"); 215 ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(); 216 operations.add(ContentProviderOperation.newInsert(uri) 217 .withValue("column1", "foo") 218 .withValue("column2", 5) 219 .build()); 220 operations.add(ContentProviderOperation.newUpdate(uri) 221 .withSelection("id_column", new String[] { "99" }) 222 .withValue("column1", "bar") 223 .build()); 224 operations.add(ContentProviderOperation.newDelete(uri) 225 .withSelection("id_column", new String[] { "11" }) 226 .build()); 227 ContentProviderResult[] result = contentResolver.applyBatch(AUTHORITY, operations); 228 229 resultOperations = shadowContentResolver.getContentProviderOperations(AUTHORITY); 230 assertThat(resultOperations, equalTo(operations)); 231 assertThat(result, equalTo(contentProviderResults)); 232 } 233 234 @Test 235 public void shouldKeepTrackOfSyncRequests() throws Exception { 236 ShadowContentResolver.Status status = ShadowContentResolver.getStatus(a, AUTHORITY, true); 237 assertNotNull(status); 238 assertThat(status.syncRequests, equalTo(0)); 239 ContentResolver.requestSync(a, AUTHORITY, new Bundle()); 240 assertThat(status.syncRequests, equalTo(1)); 241 assertNotNull(status.syncExtras); 242 } 243 244 @Test 245 public void shouldSetIsSyncable() throws Exception { 246 assertThat(ContentResolver.getIsSyncable(a, AUTHORITY), equalTo(-1)); 247 assertThat(ContentResolver.getIsSyncable(b, AUTHORITY), equalTo(-1)); 248 ContentResolver.setIsSyncable(a, AUTHORITY, 1); 249 ContentResolver.setIsSyncable(b, AUTHORITY, 2); 250 assertThat(ContentResolver.getIsSyncable(a, AUTHORITY), equalTo(1)); 251 assertThat(ContentResolver.getIsSyncable(b, AUTHORITY), equalTo(2)); 252 } 253 254 @Test 255 public void shouldSetSyncAutomatically() throws Exception { 256 assertFalse(ContentResolver.getSyncAutomatically(a, AUTHORITY)); 257 ContentResolver.setSyncAutomatically(a, AUTHORITY, true); 258 assertTrue(ContentResolver.getSyncAutomatically(a, AUTHORITY)); 259 } 260 261 @Test 262 public void shouldAddPeriodicSync() throws Exception { 263 ContentResolver.addPeriodicSync(a, AUTHORITY, new Bundle(), 6000l); 264 ShadowContentResolver.Status status = ShadowContentResolver.getStatus(a, AUTHORITY); 265 assertNotNull(status); 266 assertThat(status.syncs.size(), is(1)); 267 assertThat(status.syncs.get(0).period, is(6000l)); 268 assertNotNull(status.syncs.get(0).extras); 269 } 270 271 @Test 272 public void shouldRemovePeriodSync() throws Exception { 273 ContentResolver.addPeriodicSync(a, AUTHORITY, new Bundle(), 6000l); 274 ContentResolver.removePeriodicSync(a, AUTHORITY, new Bundle()); 275 assertThat(ShadowContentResolver.getStatus(a, AUTHORITY).syncs.size(), is(0)); 276 } 277 278 @Test 279 public void shouldGetPeriodSyncs() throws Exception { 280 assertThat(ContentResolver.getPeriodicSyncs(a, AUTHORITY).size(), is(0)); 281 ContentResolver.addPeriodicSync(a, AUTHORITY, new Bundle(), 6000l); 282 283 List<PeriodicSync> syncs = ContentResolver.getPeriodicSyncs(a, AUTHORITY); 284 assertThat(syncs.size(), is(1)); 285 286 PeriodicSync first = syncs.get(0); 287 assertThat(first.account, equalTo(a)); 288 assertThat(first.authority, equalTo(AUTHORITY)); 289 assertThat(first.period, equalTo(6000l)); 290 assertNotNull(first.extras); 291 } 292 293 @Test 294 public void shouldValidateSyncExtras() throws Exception { 295 Bundle bundle = new Bundle(); 296 bundle.putString("foo", "strings"); 297 bundle.putLong("long", 10l); 298 bundle.putDouble("double", 10.0d); 299 bundle.putFloat("float", 10.0f); 300 bundle.putInt("int", 10); 301 bundle.putParcelable("account", a); 302 ContentResolver.validateSyncExtrasBundle(bundle); 303 } 304 305 @Test(expected = IllegalArgumentException.class) 306 public void shouldValidateSyncExtrasAndThrow() throws Exception { 307 Bundle bundle = new Bundle(); 308 bundle.putParcelable("intent", new Intent()); 309 ContentResolver.validateSyncExtrasBundle(bundle); 310 } 311 312 @Test 313 public void shouldSetMasterSyncAutomatically() throws Exception { 314 assertFalse(ContentResolver.getMasterSyncAutomatically()); 315 ContentResolver.setMasterSyncAutomatically(true); 316 assertTrue(ContentResolver.getMasterSyncAutomatically()); 317 } 318 319 @Test 320 public void shouldDelegateCallsToRegisteredProvider() throws Exception { 321 ShadowContentResolver.registerProvider(AUTHORITY, new ContentProvider() { 322 @Override public boolean onCreate() { 323 return false; 324 } 325 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 326 return new TestCursor(); 327 } 328 @Override public Uri insert(Uri uri, ContentValues values) { 329 return null; 330 } 331 @Override public int delete(Uri uri, String selection, String[] selectionArgs) { 332 return -1; 333 } 334 @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { 335 return -1; 336 } 337 @Override public String getType(Uri uri) { 338 return null; 339 } 340 }); 341 final Uri uri = Uri.parse("content://"+AUTHORITY+"/some/path"); 342 final Uri unrelated = Uri.parse("content://unrelated/some/path"); 343 344 assertNotNull(contentResolver.query(uri, null, null, null, null)); 345 assertNull(contentResolver.insert(uri, new ContentValues())); 346 assertThat(contentResolver.delete(uri, null, null), is(-1)); 347 assertThat(contentResolver.update(uri, new ContentValues(), null, null), is(-1)); 348 349 assertNull(contentResolver.query(unrelated, null, null, null, null)); 350 assertNotNull(contentResolver.insert(unrelated, new ContentValues())); 351 assertThat(contentResolver.delete(unrelated, null, null), is(1)); 352 assertThat(contentResolver.update(unrelated, new ContentValues(), null, null), is(0)); 353 } 354 355 static class QueryParamTrackingTestCursor extends TestCursor { 356 public Uri uri; 357 public String[] projection; 358 public String selection; 359 public String[] selectionArgs; 360 public String sortOrder; 361 362 @Override 363 public void setQuery(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { 364 this.uri = uri; 365 this.projection = projection; 366 this.selection = selection; 367 this.selectionArgs = selectionArgs; 368 this.sortOrder = sortOrder; 369 } 370 } 371} 372