1 /* 2 * Copyright (C) 2008 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.content.cts; 18 19 import android.accounts.Account; 20 import android.content.ContentProviderClient; 21 import android.content.ContentResolver; 22 import android.content.ContentValues; 23 import android.content.Context; 24 import android.content.res.AssetFileDescriptor; 25 import android.database.ContentObserver; 26 import android.database.Cursor; 27 import android.net.Uri; 28 import android.os.Bundle; 29 import android.os.CancellationSignal; 30 import android.os.OperationCanceledException; 31 import android.os.ParcelFileDescriptor; 32 import android.os.RemoteException; 33 import android.test.AndroidTestCase; 34 import android.util.Log; 35 36 import com.android.compatibility.common.util.PollingCheck; 37 import com.android.internal.util.ArrayUtils; 38 39 import java.io.FileInputStream; 40 import java.io.FileNotFoundException; 41 import java.io.IOException; 42 import java.io.InputStream; 43 import java.io.InputStreamReader; 44 import java.io.OutputStream; 45 46 public class ContentResolverTest extends AndroidTestCase { 47 private final static String COLUMN_ID_NAME = "_id"; 48 private final static String COLUMN_KEY_NAME = "key"; 49 private final static String COLUMN_VALUE_NAME = "value"; 50 51 private static final String AUTHORITY = "ctstest"; 52 private static final Uri TABLE1_URI = Uri.parse("content://" + AUTHORITY + "/testtable1/"); 53 private static final Uri TABLE1_CROSS_URI = 54 Uri.parse("content://" + AUTHORITY + "/testtable1/cross"); 55 private static final Uri TABLE2_URI = Uri.parse("content://" + AUTHORITY + "/testtable2/"); 56 57 private static final Uri LEVEL1_URI = Uri.parse("content://" + AUTHORITY + "/level/"); 58 private static final Uri LEVEL2_URI = Uri.parse("content://" + AUTHORITY + "/level/child"); 59 private static final Uri LEVEL3_URI = Uri.parse("content://" + AUTHORITY 60 + "/level/child/grandchild/"); 61 62 private static final String REMOTE_AUTHORITY = "remotectstest"; 63 private static final Uri REMOTE_TABLE1_URI = Uri.parse("content://" 64 + REMOTE_AUTHORITY + "/testtable1/"); 65 private static final Uri REMOTE_SELF_URI = Uri.parse("content://" 66 + REMOTE_AUTHORITY + "/self/"); 67 private static final Uri REMOTE_CRASH_URI = Uri.parse("content://" 68 + REMOTE_AUTHORITY + "/crash/"); 69 70 private static final Account ACCOUNT = new Account("cts", "cts"); 71 72 private static final String KEY1 = "key1"; 73 private static final String KEY2 = "key2"; 74 private static final String KEY3 = "key3"; 75 private static final int VALUE1 = 1; 76 private static final int VALUE2 = 2; 77 private static final int VALUE3 = 3; 78 79 private static final String TEST_PACKAGE_NAME = "android.content.cts"; 80 81 private Context mContext; 82 private ContentResolver mContentResolver; 83 private Cursor mCursor; 84 85 @Override setUp()86 protected void setUp() throws Exception { 87 super.setUp(); 88 89 mContext = getContext(); 90 mContentResolver = mContext.getContentResolver(); 91 92 MockContentProvider.setCrashOnLaunch(mContext, false); 93 94 // add three rows to database when every test case start. 95 ContentValues values = new ContentValues(); 96 97 values.put(COLUMN_KEY_NAME, KEY1); 98 values.put(COLUMN_VALUE_NAME, VALUE1); 99 mContentResolver.insert(TABLE1_URI, values); 100 mContentResolver.insert(REMOTE_TABLE1_URI, values); 101 102 values.put(COLUMN_KEY_NAME, KEY2); 103 values.put(COLUMN_VALUE_NAME, VALUE2); 104 mContentResolver.insert(TABLE1_URI, values); 105 mContentResolver.insert(REMOTE_TABLE1_URI, values); 106 107 values.put(COLUMN_KEY_NAME, KEY3); 108 values.put(COLUMN_VALUE_NAME, VALUE3); 109 mContentResolver.insert(TABLE1_URI, values); 110 mContentResolver.insert(REMOTE_TABLE1_URI, values); 111 } 112 113 @Override tearDown()114 protected void tearDown() throws Exception { 115 mContentResolver.delete(TABLE1_URI, null, null); 116 if ( null != mCursor && !mCursor.isClosed() ) { 117 mCursor.close(); 118 } 119 mContentResolver.delete(REMOTE_TABLE1_URI, null, null); 120 if ( null != mCursor && !mCursor.isClosed() ) { 121 mCursor.close(); 122 } 123 super.tearDown(); 124 } 125 testConstructor()126 public void testConstructor() { 127 assertNotNull(mContentResolver); 128 } 129 testCrashOnLaunch()130 public void testCrashOnLaunch() { 131 // This test is going to make sure that the platform deals correctly 132 // with a content provider process going away while a client is waiting 133 // for it to come up. 134 // First, we need to make sure our provider process is gone. Goodbye! 135 ContentProviderClient client = mContentResolver.acquireContentProviderClient( 136 REMOTE_AUTHORITY); 137 // We are going to do something wrong here... release the client first, 138 // so the act of killing it doesn't kill our own process. 139 client.release(); 140 try { 141 client.delete(REMOTE_SELF_URI, null, null); 142 } catch (RemoteException e) { 143 } 144 // Now make sure the thing is actually gone. 145 boolean gone = true; 146 try { 147 client.getType(REMOTE_TABLE1_URI); 148 gone = false; 149 } catch (RemoteException e) { 150 } 151 if (!gone) { 152 fail("Content provider process is not gone!"); 153 } 154 try { 155 MockContentProvider.setCrashOnLaunch(mContext, true); 156 String type1 = mContentResolver.getType(REMOTE_TABLE1_URI); 157 assertFalse(MockContentProvider.getCrashOnLaunch(mContext)); 158 assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 159 } finally { 160 MockContentProvider.setCrashOnLaunch(mContext, false); 161 } 162 } 163 testUnstableToStableRefs()164 public void testUnstableToStableRefs() { 165 // Get an unstable refrence on the remote content provider. 166 ContentProviderClient uClient = mContentResolver.acquireUnstableContentProviderClient( 167 REMOTE_AUTHORITY); 168 // Verify we can access it. 169 String type1 = mContentResolver.getType(REMOTE_TABLE1_URI); 170 assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 171 172 // Get a stable reference on the remote content provider. 173 ContentProviderClient sClient = mContentResolver.acquireContentProviderClient( 174 REMOTE_AUTHORITY); 175 // Verify we can still access it. 176 type1 = mContentResolver.getType(REMOTE_TABLE1_URI); 177 assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 178 179 // Release unstable reference. 180 uClient.release(); 181 // Verify we can still access it. 182 type1 = mContentResolver.getType(REMOTE_TABLE1_URI); 183 assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 184 185 // Release stable reference, removing last ref. 186 sClient.release(); 187 // Kill it. Note that a bug at this point where it causes our own 188 // process to be killed will result in the entire test failing. 189 try { 190 Log.i("ContentResolverTest", 191 "Killing remote client -- if test process goes away, that is why!"); 192 uClient.delete(REMOTE_SELF_URI, null, null); 193 } catch (RemoteException e) { 194 } 195 // Make sure the remote client is actually gone. 196 boolean gone = true; 197 try { 198 sClient.getType(REMOTE_TABLE1_URI); 199 gone = false; 200 } catch (RemoteException e) { 201 } 202 if (!gone) { 203 fail("Content provider process is not gone!"); 204 } 205 } 206 testStableToUnstableRefs()207 public void testStableToUnstableRefs() { 208 // Get a stable reference on the remote content provider. 209 ContentProviderClient sClient = mContentResolver.acquireContentProviderClient( 210 REMOTE_AUTHORITY); 211 // Verify we can still access it. 212 String type1 = mContentResolver.getType(REMOTE_TABLE1_URI); 213 assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 214 215 // Get an unstable refrence on the remote content provider. 216 ContentProviderClient uClient = mContentResolver.acquireUnstableContentProviderClient( 217 REMOTE_AUTHORITY); 218 // Verify we can access it. 219 type1 = mContentResolver.getType(REMOTE_TABLE1_URI); 220 assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 221 222 // Release stable reference, leaving only an unstable ref. 223 sClient.release(); 224 225 // Kill it. Note that a bug at this point where it causes our own 226 // process to be killed will result in the entire test failing. 227 try { 228 Log.i("ContentResolverTest", 229 "Killing remote client -- if test process goes away, that is why!"); 230 uClient.delete(REMOTE_SELF_URI, null, null); 231 } catch (RemoteException e) { 232 } 233 // Make sure the remote client is actually gone. 234 boolean gone = true; 235 try { 236 uClient.getType(REMOTE_TABLE1_URI); 237 gone = false; 238 } catch (RemoteException e) { 239 } 240 if (!gone) { 241 fail("Content provider process is not gone!"); 242 } 243 244 // Release unstable reference. 245 uClient.release(); 246 } 247 testGetType()248 public void testGetType() { 249 String type1 = mContentResolver.getType(TABLE1_URI); 250 assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 251 252 String type2 = mContentResolver.getType(TABLE2_URI); 253 assertTrue(type2.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 254 255 Uri invalidUri = Uri.parse("abc"); 256 assertNull(mContentResolver.getType(invalidUri)); 257 258 try { 259 mContentResolver.getType(null); 260 fail("did not throw NullPointerException when Uri is null."); 261 } catch (NullPointerException e) { 262 //expected. 263 } 264 } 265 testUnstableGetType()266 public void testUnstableGetType() { 267 // Get an unstable refrence on the remote content provider. 268 ContentProviderClient client = mContentResolver.acquireUnstableContentProviderClient( 269 REMOTE_AUTHORITY); 270 // Verify we can access it. 271 String type1 = mContentResolver.getType(REMOTE_TABLE1_URI); 272 assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 273 274 // Kill it. Note that a bug at this point where it causes our own 275 // process to be killed will result in the entire test failing. 276 try { 277 Log.i("ContentResolverTest", 278 "Killing remote client -- if test process goes away, that is why!"); 279 client.delete(REMOTE_SELF_URI, null, null); 280 } catch (RemoteException e) { 281 } 282 // Make sure the remote client is actually gone. 283 boolean gone = true; 284 try { 285 client.getType(REMOTE_TABLE1_URI); 286 gone = false; 287 } catch (RemoteException e) { 288 } 289 if (!gone) { 290 fail("Content provider process is not gone!"); 291 } 292 293 // Now the remote client is gone, can we recover? 294 // Release our old reference. 295 client.release(); 296 // Get a new reference. 297 client = mContentResolver.acquireUnstableContentProviderClient(REMOTE_AUTHORITY); 298 // Verify we can access it. 299 type1 = mContentResolver.getType(REMOTE_TABLE1_URI); 300 assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0)); 301 } 302 testQuery()303 public void testQuery() { 304 mCursor = mContentResolver.query(TABLE1_URI, null, null, null); 305 306 assertNotNull(mCursor); 307 assertEquals(3, mCursor.getCount()); 308 assertEquals(3, mCursor.getColumnCount()); 309 310 mCursor.moveToLast(); 311 assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 312 assertEquals(KEY3, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 313 assertEquals(VALUE3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 314 315 mCursor.moveToPrevious(); 316 assertEquals(2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 317 assertEquals(KEY2, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 318 assertEquals(VALUE2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 319 mCursor.close(); 320 } 321 testQuery_WithSqlSelectionArgs()322 public void testQuery_WithSqlSelectionArgs() { 323 Bundle queryArgs = new Bundle(); 324 queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, COLUMN_ID_NAME + "=?"); 325 queryArgs.putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, new String[] {"1"}); 326 327 mCursor = mContentResolver.query(TABLE1_URI, null, queryArgs, null); 328 assertNotNull(mCursor); 329 assertEquals(1, mCursor.getCount()); 330 assertEquals(3, mCursor.getColumnCount()); 331 332 mCursor.moveToFirst(); 333 assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 334 assertEquals(KEY1, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 335 assertEquals(VALUE1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 336 mCursor.close(); 337 338 queryArgs.putString(ContentResolver.QUERY_ARG_SQL_SELECTION, COLUMN_KEY_NAME + "=?"); 339 queryArgs.putStringArray(ContentResolver.QUERY_ARG_SQL_SELECTION_ARGS, new String[] {KEY3}); 340 mCursor = mContentResolver.query(TABLE1_URI, null, queryArgs, null); 341 assertNotNull(mCursor); 342 assertEquals(1, mCursor.getCount()); 343 assertEquals(3, mCursor.getColumnCount()); 344 345 mCursor.moveToFirst(); 346 assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 347 assertEquals(KEY3, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 348 assertEquals(VALUE3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 349 mCursor.close(); 350 } 351 352 /* 353 * NOTE: this test is implicitly coupled to the implementation 354 * of MockContentProvider#query, specifically the facts: 355 * 356 * - it does *not* override the query w/ Bundle methods 357 * - it receives the auto-generated sql format arguments (supplied by the framework) 358 * - it is backed by sqlite and forwards the sql formatted args. 359 */ testQuery_SqlSortingFromBundleArgs()360 public void testQuery_SqlSortingFromBundleArgs() { 361 362 mContentResolver.delete(TABLE1_URI, null, null); 363 ContentValues values = new ContentValues(); 364 365 values.put(COLUMN_KEY_NAME, "0"); 366 values.put(COLUMN_VALUE_NAME, "abc"); 367 mContentResolver.insert(TABLE1_URI, values); 368 369 values.put(COLUMN_KEY_NAME, "1"); 370 values.put(COLUMN_VALUE_NAME, "DEF"); 371 mContentResolver.insert(TABLE1_URI, values); 372 373 values.put(COLUMN_KEY_NAME, "2"); 374 values.put(COLUMN_VALUE_NAME, "ghi"); 375 mContentResolver.insert(TABLE1_URI, values); 376 377 String[] sortCols = new String[] { COLUMN_VALUE_NAME }; 378 Bundle queryArgs = new Bundle(); 379 queryArgs.putStringArray( 380 ContentResolver.QUERY_ARG_SORT_COLUMNS, 381 sortCols); 382 383 // Sort ascending... 384 queryArgs.putInt( 385 ContentResolver.QUERY_ARG_SORT_DIRECTION, 386 ContentResolver.QUERY_SORT_DIRECTION_ASCENDING); 387 388 mCursor = mContentResolver.query(TABLE1_URI, sortCols, queryArgs, null); 389 int col = mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME); 390 391 mCursor.moveToNext(); 392 assertEquals("DEF", mCursor.getString(col)); 393 mCursor.moveToNext(); 394 assertEquals("abc", mCursor.getString(col)); 395 mCursor.moveToNext(); 396 assertEquals("ghi", mCursor.getString(col)); 397 398 mCursor.close(); 399 400 // Nocase collation, descending... 401 queryArgs.putInt( 402 ContentResolver.QUERY_ARG_SORT_DIRECTION, 403 ContentResolver.QUERY_SORT_DIRECTION_DESCENDING); 404 queryArgs.putInt( 405 ContentResolver.QUERY_ARG_SORT_COLLATION, 406 java.text.Collator.SECONDARY); 407 408 mCursor = mContentResolver.query(TABLE1_URI, null, queryArgs, null); 409 col = mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME); 410 411 mCursor.moveToNext(); 412 assertEquals("ghi", mCursor.getString(col)); 413 mCursor.moveToNext(); 414 assertEquals("DEF", mCursor.getString(col)); 415 mCursor.moveToNext(); 416 assertEquals("abc", mCursor.getString(col)); 417 418 mCursor.close(); 419 } 420 421 /** 422 * Verifies that paging information is correctly relayed, and that 423 * honored arguments from a supporting client are returned correctly. 424 */ testQuery_PagedResults()425 public void testQuery_PagedResults() { 426 427 Bundle queryArgs = new Bundle(); 428 queryArgs.putInt(ContentResolver.QUERY_ARG_OFFSET, 10); 429 queryArgs.putInt(ContentResolver.QUERY_ARG_LIMIT, 3); 430 queryArgs.putInt(TestPagingContentProvider.RECORD_COUNT, 100); 431 432 mCursor = mContentResolver.query( 433 TestPagingContentProvider.PAGED_DATA_URI, null, queryArgs, null); 434 435 Bundle extras = mCursor.getExtras(); 436 extras = extras != null ? extras : Bundle.EMPTY; 437 438 assertEquals(3, mCursor.getCount()); 439 assertTrue(extras.containsKey(ContentResolver.EXTRA_TOTAL_COUNT)); 440 assertEquals(100, extras.getInt(ContentResolver.EXTRA_TOTAL_COUNT)); 441 442 String[] honoredArgs = extras.getStringArray(ContentResolver.EXTRA_HONORED_ARGS); 443 assertNotNull(honoredArgs); 444 assertTrue(ArrayUtils.contains(honoredArgs, ContentResolver.QUERY_ARG_OFFSET)); 445 assertTrue(ArrayUtils.contains(honoredArgs, ContentResolver.QUERY_ARG_LIMIT)); 446 447 int col = mCursor.getColumnIndexOrThrow(TestPagingContentProvider.COLUMN_POS); 448 449 mCursor.moveToNext(); 450 assertEquals(10, mCursor.getInt(col)); 451 mCursor.moveToNext(); 452 assertEquals(11, mCursor.getInt(col)); 453 mCursor.moveToNext(); 454 assertEquals(12, mCursor.getInt(col)); 455 456 assertFalse(mCursor.moveToNext()); 457 458 mCursor.close(); 459 } 460 testQuery_NullUriThrows()461 public void testQuery_NullUriThrows() { 462 try { 463 mContentResolver.query(null, null, null, null, null); 464 fail("did not throw NullPointerException when uri is null."); 465 } catch (NullPointerException e) { 466 //expected. 467 } 468 } 469 testCrashingQuery()470 public void testCrashingQuery() { 471 try { 472 MockContentProvider.setCrashOnLaunch(mContext, true); 473 mCursor = mContentResolver.query(REMOTE_CRASH_URI, null, null, null, null); 474 assertFalse(MockContentProvider.getCrashOnLaunch(mContext)); 475 } finally { 476 MockContentProvider.setCrashOnLaunch(mContext, false); 477 } 478 479 assertNotNull(mCursor); 480 assertEquals(3, mCursor.getCount()); 481 assertEquals(3, mCursor.getColumnCount()); 482 483 mCursor.moveToLast(); 484 assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 485 assertEquals(KEY3, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 486 assertEquals(VALUE3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 487 488 mCursor.moveToPrevious(); 489 assertEquals(2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 490 assertEquals(KEY2, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 491 assertEquals(VALUE2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 492 mCursor.close(); 493 } 494 testCancelableQuery_WhenNotCanceled_ReturnsResultSet()495 public void testCancelableQuery_WhenNotCanceled_ReturnsResultSet() { 496 CancellationSignal cancellationSignal = new CancellationSignal(); 497 498 Cursor cursor = mContentResolver.query(TABLE1_URI, null, null, null, null, 499 cancellationSignal); 500 assertEquals(3, cursor.getCount()); 501 cursor.close(); 502 } 503 testCancelableQuery_WhenCanceledBeforeQuery_ThrowsImmediately()504 public void testCancelableQuery_WhenCanceledBeforeQuery_ThrowsImmediately() { 505 CancellationSignal cancellationSignal = new CancellationSignal(); 506 cancellationSignal.cancel(); 507 508 try { 509 mContentResolver.query(TABLE1_URI, null, null, null, null, cancellationSignal); 510 fail("Expected OperationCanceledException"); 511 } catch (OperationCanceledException ex) { 512 // expected 513 } 514 } 515 testCancelableQuery_WhenCanceledDuringLongRunningQuery_CancelsQueryAndThrows()516 public void testCancelableQuery_WhenCanceledDuringLongRunningQuery_CancelsQueryAndThrows() { 517 // Populate a table with a bunch of integers. 518 mContentResolver.delete(TABLE1_URI, null, null); 519 ContentValues values = new ContentValues(); 520 for (int i = 0; i < 100; i++) { 521 values.put(COLUMN_KEY_NAME, i); 522 values.put(COLUMN_VALUE_NAME, i); 523 mContentResolver.insert(TABLE1_URI, values); 524 } 525 526 for (int i = 0; i < 5; i++) { 527 final CancellationSignal cancellationSignal = new CancellationSignal(); 528 Thread cancellationThread = new Thread() { 529 @Override 530 public void run() { 531 try { 532 Thread.sleep(300); 533 } catch (InterruptedException ex) { 534 } 535 cancellationSignal.cancel(); 536 } 537 }; 538 try { 539 // Build an unsatisfiable 5-way cross-product query over 100 values but 540 // produces no output. This should force SQLite to loop for a long time 541 // as it tests 10^10 combinations. 542 cancellationThread.start(); 543 544 final long startTime = System.nanoTime(); 545 try { 546 mContentResolver.query(TABLE1_CROSS_URI, null, 547 "a.value + b.value + c.value + d.value + e.value > 1000000", 548 null, null, cancellationSignal); 549 fail("Expected OperationCanceledException"); 550 } catch (OperationCanceledException ex) { 551 // expected 552 } 553 554 // We want to confirm that the query really was running and then got 555 // canceled midway. 556 final long waitTime = System.nanoTime() - startTime; 557 if (waitTime > 150 * 1000000L && waitTime < 600 * 1000000L) { 558 return; // success! 559 } 560 } finally { 561 try { 562 cancellationThread.join(); 563 } catch (InterruptedException e) { 564 } 565 } 566 } 567 568 // Occasionally we might miss the timing deadline due to factors in the 569 // environment, but if after several trials we still couldn't demonstrate 570 // that the query was canceled, then the test must be broken. 571 fail("Could not prove that the query actually canceled midway during execution."); 572 } 573 testOpenInputStream()574 public void testOpenInputStream() throws IOException { 575 final Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + 576 "://" + TEST_PACKAGE_NAME + "/" + R.drawable.pass); 577 578 InputStream is = mContentResolver.openInputStream(uri); 579 assertNotNull(is); 580 is.close(); 581 582 final Uri invalidUri = Uri.parse("abc"); 583 try { 584 mContentResolver.openInputStream(invalidUri); 585 fail("did not throw FileNotFoundException when uri is invalid."); 586 } catch (FileNotFoundException e) { 587 //expected. 588 } 589 } 590 testOpenOutputStream()591 public void testOpenOutputStream() throws IOException { 592 Uri uri = Uri.parse(ContentResolver.SCHEME_FILE + "://" + 593 getContext().getCacheDir().getAbsolutePath() + 594 "/temp.jpg"); 595 OutputStream os = mContentResolver.openOutputStream(uri); 596 assertNotNull(os); 597 os.close(); 598 599 os = mContentResolver.openOutputStream(uri, "wa"); 600 assertNotNull(os); 601 os.close(); 602 603 uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + 604 "://" + TEST_PACKAGE_NAME + "/" + R.raw.testimage); 605 try { 606 mContentResolver.openOutputStream(uri); 607 fail("did not throw FileNotFoundException when scheme is not accepted."); 608 } catch (FileNotFoundException e) { 609 //expected. 610 } 611 612 try { 613 mContentResolver.openOutputStream(uri, "w"); 614 fail("did not throw FileNotFoundException when scheme is not accepted."); 615 } catch (FileNotFoundException e) { 616 //expected. 617 } 618 619 Uri invalidUri = Uri.parse("abc"); 620 try { 621 mContentResolver.openOutputStream(invalidUri); 622 fail("did not throw FileNotFoundException when uri is invalid."); 623 } catch (FileNotFoundException e) { 624 //expected. 625 } 626 627 try { 628 mContentResolver.openOutputStream(invalidUri, "w"); 629 fail("did not throw FileNotFoundException when uri is invalid."); 630 } catch (FileNotFoundException e) { 631 //expected. 632 } 633 } 634 testOpenAssetFileDescriptor()635 public void testOpenAssetFileDescriptor() throws IOException { 636 Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + 637 "://" + TEST_PACKAGE_NAME + "/" + R.raw.testimage); 638 639 AssetFileDescriptor afd = mContentResolver.openAssetFileDescriptor(uri, "r"); 640 assertNotNull(afd); 641 afd.close(); 642 643 try { 644 mContentResolver.openAssetFileDescriptor(uri, "d"); 645 fail("did not throw FileNotFoundException when mode is unknown."); 646 } catch (FileNotFoundException e) { 647 //expected. 648 } 649 650 Uri invalidUri = Uri.parse("abc"); 651 try { 652 mContentResolver.openAssetFileDescriptor(invalidUri, "r"); 653 fail("did not throw FileNotFoundException when uri is invalid."); 654 } catch (FileNotFoundException e) { 655 //expected. 656 } 657 } 658 consumeAssetFileDescriptor(AssetFileDescriptor afd)659 private String consumeAssetFileDescriptor(AssetFileDescriptor afd) 660 throws IOException { 661 FileInputStream stream = null; 662 try { 663 stream = afd.createInputStream(); 664 InputStreamReader reader = new InputStreamReader(stream, "UTF-8"); 665 666 // Got it... copy the stream into a local string and return it. 667 StringBuilder builder = new StringBuilder(128); 668 char[] buffer = new char[8192]; 669 int len; 670 while ((len=reader.read(buffer)) > 0) { 671 builder.append(buffer, 0, len); 672 } 673 return builder.toString(); 674 675 } finally { 676 if (stream != null) { 677 try { 678 stream.close(); 679 } catch (IOException e) { 680 } 681 } 682 } 683 684 } 685 testCrashingOpenAssetFileDescriptor()686 public void testCrashingOpenAssetFileDescriptor() throws IOException { 687 AssetFileDescriptor afd = null; 688 try { 689 MockContentProvider.setCrashOnLaunch(mContext, true); 690 afd = mContentResolver.openAssetFileDescriptor(REMOTE_CRASH_URI, "rw"); 691 assertFalse(MockContentProvider.getCrashOnLaunch(mContext)); 692 assertNotNull(afd); 693 String str = consumeAssetFileDescriptor(afd); 694 afd = null; 695 assertEquals(str, "This is the openAssetFile test data!"); 696 } finally { 697 MockContentProvider.setCrashOnLaunch(mContext, false); 698 if (afd != null) { 699 afd.close(); 700 } 701 } 702 703 // Make sure a content provider crash at this point won't hurt us. 704 ContentProviderClient uClient = mContentResolver.acquireUnstableContentProviderClient( 705 REMOTE_AUTHORITY); 706 // Kill it. Note that a bug at this point where it causes our own 707 // process to be killed will result in the entire test failing. 708 try { 709 Log.i("ContentResolverTest", 710 "Killing remote client -- if test process goes away, that is why!"); 711 uClient.delete(REMOTE_SELF_URI, null, null); 712 } catch (RemoteException e) { 713 } 714 uClient.release(); 715 } 716 testCrashingOpenTypedAssetFileDescriptor()717 public void testCrashingOpenTypedAssetFileDescriptor() throws IOException { 718 AssetFileDescriptor afd = null; 719 try { 720 MockContentProvider.setCrashOnLaunch(mContext, true); 721 afd = mContentResolver.openTypedAssetFileDescriptor( 722 REMOTE_CRASH_URI, "text/plain", null); 723 assertFalse(MockContentProvider.getCrashOnLaunch(mContext)); 724 assertNotNull(afd); 725 String str = consumeAssetFileDescriptor(afd); 726 afd = null; 727 assertEquals(str, "This is the openTypedAssetFile test data!"); 728 } finally { 729 MockContentProvider.setCrashOnLaunch(mContext, false); 730 if (afd != null) { 731 afd.close(); 732 } 733 } 734 735 // Make sure a content provider crash at this point won't hurt us. 736 ContentProviderClient uClient = mContentResolver.acquireUnstableContentProviderClient( 737 REMOTE_AUTHORITY); 738 // Kill it. Note that a bug at this point where it causes our own 739 // process to be killed will result in the entire test failing. 740 try { 741 Log.i("ContentResolverTest", 742 "Killing remote client -- if test process goes away, that is why!"); 743 uClient.delete(REMOTE_SELF_URI, null, null); 744 } catch (RemoteException e) { 745 } 746 uClient.release(); 747 } 748 testOpenFileDescriptor()749 public void testOpenFileDescriptor() throws IOException { 750 Uri uri = Uri.parse(ContentResolver.SCHEME_FILE + "://" + 751 getContext().getCacheDir().getAbsolutePath() + 752 "/temp.jpg"); 753 ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(uri, "w"); 754 assertNotNull(pfd); 755 pfd.close(); 756 757 try { 758 mContentResolver.openFileDescriptor(uri, "d"); 759 fail("did not throw IllegalArgumentException when mode is unknown."); 760 } catch (IllegalArgumentException e) { 761 //expected. 762 } 763 764 Uri invalidUri = Uri.parse("abc"); 765 try { 766 mContentResolver.openFileDescriptor(invalidUri, "w"); 767 fail("did not throw FileNotFoundException when uri is invalid."); 768 } catch (FileNotFoundException e) { 769 //expected. 770 } 771 772 uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + 773 "://" + TEST_PACKAGE_NAME + "/" + R.raw.testimage); 774 try { 775 mContentResolver.openFileDescriptor(uri, "w"); 776 fail("did not throw FileNotFoundException when scheme is not accepted."); 777 } catch (FileNotFoundException e) { 778 //expected. 779 } 780 } 781 testInsert()782 public void testInsert() { 783 String key4 = "key4"; 784 String key5 = "key5"; 785 int value4 = 4; 786 int value5 = 5; 787 String key4Selection = COLUMN_KEY_NAME + "=\"" + key4 + "\""; 788 789 mCursor = mContentResolver.query(TABLE1_URI, null, key4Selection, null, null); 790 assertEquals(0, mCursor.getCount()); 791 mCursor.close(); 792 793 ContentValues values = new ContentValues(); 794 values.put(COLUMN_KEY_NAME, key4); 795 values.put(COLUMN_VALUE_NAME, value4); 796 Uri uri = mContentResolver.insert(TABLE1_URI, values); 797 assertNotNull(uri); 798 799 mCursor = mContentResolver.query(TABLE1_URI, null, key4Selection, null, null); 800 assertNotNull(mCursor); 801 assertEquals(1, mCursor.getCount()); 802 803 mCursor.moveToFirst(); 804 assertEquals(4, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 805 assertEquals(key4, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 806 assertEquals(value4, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 807 mCursor.close(); 808 809 values.put(COLUMN_KEY_NAME, key5); 810 values.put(COLUMN_VALUE_NAME, value5); 811 uri = mContentResolver.insert(TABLE1_URI, values); 812 assertNotNull(uri); 813 814 // check returned uri 815 mCursor = mContentResolver.query(uri, null, null, null, null); 816 assertNotNull(mCursor); 817 assertEquals(1, mCursor.getCount()); 818 819 mCursor.moveToLast(); 820 assertEquals(5, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 821 assertEquals(key5, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 822 assertEquals(value5, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 823 mCursor.close(); 824 825 try { 826 mContentResolver.insert(null, values); 827 fail("did not throw NullPointerException when uri is null."); 828 } catch (NullPointerException e) { 829 //expected. 830 } 831 } 832 testBulkInsert()833 public void testBulkInsert() { 834 String key4 = "key4"; 835 String key5 = "key5"; 836 int value4 = 4; 837 int value5 = 5; 838 839 mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null); 840 assertNotNull(mCursor); 841 assertEquals(3, mCursor.getCount()); 842 mCursor.close(); 843 844 ContentValues[] cvs = new ContentValues[2]; 845 cvs[0] = new ContentValues(); 846 cvs[0].put(COLUMN_KEY_NAME, key4); 847 cvs[0].put(COLUMN_VALUE_NAME, value4); 848 849 cvs[1] = new ContentValues(); 850 cvs[1].put(COLUMN_KEY_NAME, key5); 851 cvs[1].put(COLUMN_VALUE_NAME, value5); 852 853 assertEquals(2, mContentResolver.bulkInsert(TABLE1_URI, cvs)); 854 mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null); 855 assertNotNull(mCursor); 856 assertEquals(5, mCursor.getCount()); 857 858 mCursor.moveToLast(); 859 assertEquals(5, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 860 assertEquals(key5, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 861 assertEquals(value5, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 862 863 mCursor.moveToPrevious(); 864 assertEquals(4, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 865 assertEquals(key4, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 866 assertEquals(value4, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 867 mCursor.close(); 868 869 try { 870 mContentResolver.bulkInsert(null, cvs); 871 fail("did not throw NullPointerException when uri is null."); 872 } catch (NullPointerException e) { 873 //expected. 874 } 875 } 876 testDelete()877 public void testDelete() { 878 mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null); 879 assertNotNull(mCursor); 880 assertEquals(3, mCursor.getCount()); 881 mCursor.close(); 882 883 assertEquals(3, mContentResolver.delete(TABLE1_URI, null, null)); 884 mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null); 885 assertNotNull(mCursor); 886 assertEquals(0, mCursor.getCount()); 887 mCursor.close(); 888 889 // add three rows to database. 890 ContentValues values = new ContentValues(); 891 values.put(COLUMN_KEY_NAME, KEY1); 892 values.put(COLUMN_VALUE_NAME, VALUE1); 893 mContentResolver.insert(TABLE1_URI, values); 894 895 values.put(COLUMN_KEY_NAME, KEY2); 896 values.put(COLUMN_VALUE_NAME, VALUE2); 897 mContentResolver.insert(TABLE1_URI, values); 898 899 values.put(COLUMN_KEY_NAME, KEY3); 900 values.put(COLUMN_VALUE_NAME, VALUE3); 901 mContentResolver.insert(TABLE1_URI, values); 902 903 // test delete row using selection 904 String selection = COLUMN_ID_NAME + "=2"; 905 assertEquals(1, mContentResolver.delete(TABLE1_URI, selection, null)); 906 907 mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null); 908 assertNotNull(mCursor); 909 assertEquals(2, mCursor.getCount()); 910 911 mCursor.moveToFirst(); 912 assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 913 assertEquals(KEY1, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 914 assertEquals(VALUE1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 915 916 mCursor.moveToNext(); 917 assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 918 assertEquals(KEY3, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 919 assertEquals(VALUE3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 920 mCursor.close(); 921 922 selection = COLUMN_VALUE_NAME + "=3"; 923 assertEquals(1, mContentResolver.delete(TABLE1_URI, selection, null)); 924 925 mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null); 926 assertNotNull(mCursor); 927 assertEquals(1, mCursor.getCount()); 928 929 mCursor.moveToFirst(); 930 assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 931 assertEquals(KEY1, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 932 assertEquals(VALUE1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 933 mCursor.close(); 934 935 selection = COLUMN_KEY_NAME + "=\"" + KEY1 + "\""; 936 assertEquals(1, mContentResolver.delete(TABLE1_URI, selection, null)); 937 938 mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null); 939 assertNotNull(mCursor); 940 assertEquals(0, mCursor.getCount()); 941 mCursor.close(); 942 943 try { 944 mContentResolver.delete(null, null, null); 945 fail("did not throw NullPointerException when uri is null."); 946 } catch (NullPointerException e) { 947 //expected. 948 } 949 } 950 testUpdate()951 public void testUpdate() { 952 ContentValues values = new ContentValues(); 953 String key10 = "key10"; 954 String key20 = "key20"; 955 int value10 = 10; 956 int value20 = 20; 957 958 values.put(COLUMN_KEY_NAME, key10); 959 values.put(COLUMN_VALUE_NAME, value10); 960 961 // test update all the rows. 962 assertEquals(3, mContentResolver.update(TABLE1_URI, values, null, null)); 963 mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null); 964 assertNotNull(mCursor); 965 assertEquals(3, mCursor.getCount()); 966 967 mCursor.moveToFirst(); 968 assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 969 assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 970 assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 971 972 mCursor.moveToNext(); 973 assertEquals(2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 974 assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 975 assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 976 977 mCursor.moveToLast(); 978 assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 979 assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 980 assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 981 mCursor.close(); 982 983 // test update one row using selection. 984 String selection = COLUMN_ID_NAME + "=1"; 985 values.put(COLUMN_KEY_NAME, key20); 986 values.put(COLUMN_VALUE_NAME, value20); 987 988 assertEquals(1, mContentResolver.update(TABLE1_URI, values, selection, null)); 989 mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null); 990 assertNotNull(mCursor); 991 assertEquals(3, mCursor.getCount()); 992 993 mCursor.moveToFirst(); 994 assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 995 assertEquals(key20, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 996 assertEquals(value20, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 997 998 mCursor.moveToNext(); 999 assertEquals(2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 1000 assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 1001 assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 1002 1003 mCursor.moveToLast(); 1004 assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME))); 1005 assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME))); 1006 assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME))); 1007 mCursor.close(); 1008 1009 try { 1010 mContentResolver.update(null, values, null, null); 1011 fail("did not throw NullPointerException when uri is null."); 1012 } catch (NullPointerException e) { 1013 //expected. 1014 } 1015 1016 // javadoc says it will throw NullPointerException when values are null, 1017 // but actually, it throws IllegalArgumentException here. 1018 try { 1019 mContentResolver.update(TABLE1_URI, null, null, null); 1020 fail("did not throw IllegalArgumentException when values are null."); 1021 } catch (IllegalArgumentException e) { 1022 //expected. 1023 } 1024 } 1025 testRefresh_DefaultImplReturnsFalse()1026 public void testRefresh_DefaultImplReturnsFalse() { 1027 boolean refreshed = mContentResolver.refresh(TABLE1_URI, null, null); 1028 assertFalse(refreshed); 1029 MockContentProvider.assertRefreshed(TABLE1_URI); 1030 } 1031 testRefresh_ReturnsProviderValue()1032 public void testRefresh_ReturnsProviderValue() { 1033 try { 1034 MockContentProvider.setRefreshReturnValue(true); 1035 boolean refreshed = mContentResolver.refresh(TABLE1_URI, null, null); 1036 assertTrue(refreshed); 1037 MockContentProvider.assertRefreshed(TABLE1_URI); 1038 } finally { 1039 MockContentProvider.setRefreshReturnValue(false); 1040 } 1041 } 1042 testRefresh_NullUriThrowsImmediately()1043 public void testRefresh_NullUriThrowsImmediately() { 1044 try { 1045 mContentResolver.refresh(null, null, null); 1046 fail("did not throw NullPointerException when uri is null."); 1047 } catch (NullPointerException e) { 1048 //expected. 1049 } 1050 } 1051 testRefresh_CancellableThrowsImmediately()1052 public void testRefresh_CancellableThrowsImmediately() { 1053 CancellationSignal cancellationSignal = new CancellationSignal(); 1054 cancellationSignal.cancel(); 1055 1056 try { 1057 mContentResolver.refresh(TABLE1_URI, null, cancellationSignal); 1058 fail("Expected OperationCanceledException"); 1059 } catch (OperationCanceledException ex) { 1060 // expected 1061 } 1062 } 1063 testRegisterContentObserver()1064 public void testRegisterContentObserver() { 1065 final MockContentObserver mco = new MockContentObserver(); 1066 1067 mContentResolver.registerContentObserver(TABLE1_URI, true, mco); 1068 assertFalse(mco.hadOnChanged()); 1069 1070 ContentValues values = new ContentValues(); 1071 values.put(COLUMN_KEY_NAME, "key10"); 1072 values.put(COLUMN_VALUE_NAME, 10); 1073 mContentResolver.update(TABLE1_URI, values, null, null); 1074 new PollingCheck() { 1075 @Override 1076 protected boolean check() { 1077 return mco.hadOnChanged(); 1078 } 1079 }.run(); 1080 1081 mco.reset(); 1082 mContentResolver.unregisterContentObserver(mco); 1083 assertFalse(mco.hadOnChanged()); 1084 mContentResolver.update(TABLE1_URI, values, null, null); 1085 1086 assertFalse(mco.hadOnChanged()); 1087 1088 try { 1089 mContentResolver.registerContentObserver(null, false, mco); 1090 fail("did not throw NullPointerException or IllegalArgumentException when uri is null."); 1091 } catch (NullPointerException e) { 1092 //expected. 1093 } catch (IllegalArgumentException e) { 1094 // also expected 1095 } 1096 1097 try { 1098 mContentResolver.registerContentObserver(TABLE1_URI, false, null); 1099 fail("did not throw NullPointerException when register null content observer."); 1100 } catch (NullPointerException e) { 1101 //expected. 1102 } 1103 1104 try { 1105 mContentResolver.unregisterContentObserver(null); 1106 fail("did not throw NullPointerException when unregister null content observer."); 1107 } catch (NullPointerException e) { 1108 //expected. 1109 } 1110 } 1111 testRegisterContentObserverDescendantBehavior()1112 public void testRegisterContentObserverDescendantBehavior() throws Exception { 1113 final MockContentObserver mco1 = new MockContentObserver(); 1114 final MockContentObserver mco2 = new MockContentObserver(); 1115 1116 // Register one content observer with notifyDescendants set to false, and 1117 // another with true. 1118 mContentResolver.registerContentObserver(LEVEL2_URI, false, mco1); 1119 mContentResolver.registerContentObserver(LEVEL2_URI, true, mco2); 1120 1121 // Initially nothing has happened. 1122 assertFalse(mco1.hadOnChanged()); 1123 assertFalse(mco2.hadOnChanged()); 1124 1125 // Fire a change with the exact URI. 1126 // Should signal both observers due to exact match, notifyDescendants doesn't matter. 1127 mContentResolver.notifyChange(LEVEL2_URI, null); 1128 Thread.sleep(200); 1129 assertTrue(mco1.hadOnChanged()); 1130 assertTrue(mco2.hadOnChanged()); 1131 mco1.reset(); 1132 mco2.reset(); 1133 1134 // Fire a change with a descendant URI. 1135 // Should only signal observer with notifyDescendants set to true. 1136 mContentResolver.notifyChange(LEVEL3_URI, null); 1137 Thread.sleep(200); 1138 assertFalse(mco1.hadOnChanged()); 1139 assertTrue(mco2.hadOnChanged()); 1140 mco2.reset(); 1141 1142 // Fire a change with an ancestor URI. 1143 // Should signal both observers due to ancestry, notifyDescendants doesn't matter. 1144 mContentResolver.notifyChange(LEVEL1_URI, null); 1145 Thread.sleep(200); 1146 assertTrue(mco1.hadOnChanged()); 1147 assertTrue(mco2.hadOnChanged()); 1148 mco1.reset(); 1149 mco2.reset(); 1150 1151 // Fire a change with an unrelated URI. 1152 // Should signal neither observer. 1153 mContentResolver.notifyChange(TABLE1_URI, null); 1154 Thread.sleep(200); 1155 assertFalse(mco1.hadOnChanged()); 1156 assertFalse(mco2.hadOnChanged()); 1157 } 1158 testNotifyChange1()1159 public void testNotifyChange1() { 1160 final MockContentObserver mco = new MockContentObserver(); 1161 1162 mContentResolver.registerContentObserver(TABLE1_URI, true, mco); 1163 assertFalse(mco.hadOnChanged()); 1164 1165 mContentResolver.notifyChange(TABLE1_URI, mco); 1166 new PollingCheck() { 1167 @Override 1168 protected boolean check() { 1169 return mco.hadOnChanged(); 1170 } 1171 }.run(); 1172 1173 mContentResolver.unregisterContentObserver(mco); 1174 } 1175 testNotifyChange2()1176 public void testNotifyChange2() { 1177 final MockContentObserver mco = new MockContentObserver(); 1178 1179 mContentResolver.registerContentObserver(TABLE1_URI, true, mco); 1180 assertFalse(mco.hadOnChanged()); 1181 1182 mContentResolver.notifyChange(TABLE1_URI, mco, false); 1183 new PollingCheck() { 1184 @Override 1185 protected boolean check() { 1186 return mco.hadOnChanged(); 1187 } 1188 }.run(); 1189 1190 mContentResolver.unregisterContentObserver(mco); 1191 } 1192 testStartCancelSync()1193 public void testStartCancelSync() { 1194 Bundle extras = new Bundle(); 1195 1196 extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); 1197 1198 ContentResolver.requestSync(ACCOUNT, AUTHORITY, extras); 1199 //FIXME: how to get the result to assert. 1200 1201 ContentResolver.cancelSync(ACCOUNT, AUTHORITY); 1202 //FIXME: how to assert. 1203 } 1204 testStartSyncFailure()1205 public void testStartSyncFailure() { 1206 try { 1207 ContentResolver.requestSync(null, null, null); 1208 fail("did not throw IllegalArgumentException when extras is null."); 1209 } catch (IllegalArgumentException e) { 1210 //expected. 1211 } 1212 } 1213 testValidateSyncExtrasBundle()1214 public void testValidateSyncExtrasBundle() { 1215 Bundle extras = new Bundle(); 1216 extras.putInt("Integer", 20); 1217 extras.putLong("Long", 10l); 1218 extras.putBoolean("Boolean", true); 1219 extras.putFloat("Float", 5.5f); 1220 extras.putDouble("Double", 2.5); 1221 extras.putString("String", "cts"); 1222 extras.putCharSequence("CharSequence", null); 1223 1224 ContentResolver.validateSyncExtrasBundle(extras); 1225 1226 extras.putChar("Char", 'a'); // type Char is invalid 1227 try { 1228 ContentResolver.validateSyncExtrasBundle(extras); 1229 fail("did not throw IllegalArgumentException when extras is invalide."); 1230 } catch (IllegalArgumentException e) { 1231 //expected. 1232 } 1233 } 1234 1235 private class MockContentObserver extends ContentObserver { 1236 private boolean mHadOnChanged = false; 1237 MockContentObserver()1238 public MockContentObserver() { 1239 super(null); 1240 } 1241 1242 @Override deliverSelfNotifications()1243 public boolean deliverSelfNotifications() { 1244 return true; 1245 } 1246 1247 @Override onChange(boolean selfChange)1248 public synchronized void onChange(boolean selfChange) { 1249 super.onChange(selfChange); 1250 mHadOnChanged = true; 1251 } 1252 hadOnChanged()1253 public synchronized boolean hadOnChanged() { 1254 return mHadOnChanged; 1255 } 1256 reset()1257 public synchronized void reset() { 1258 mHadOnChanged = false; 1259 } 1260 } 1261 } 1262