Home | History | Annotate | Download | only in cts
      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 com.android.cts.stub.R;
     20 
     21 import dalvik.annotation.TestLevel;
     22 import dalvik.annotation.TestTargetClass;
     23 import dalvik.annotation.TestTargetNew;
     24 import dalvik.annotation.TestTargets;
     25 import dalvik.annotation.ToBeFixed;
     26 
     27 import android.accounts.Account;
     28 import android.content.ContentResolver;
     29 import android.content.ContentValues;
     30 import android.content.Context;
     31 import android.content.res.AssetFileDescriptor;
     32 import android.database.ContentObserver;
     33 import android.database.Cursor;
     34 import android.net.Uri;
     35 import android.os.Bundle;
     36 import android.os.ParcelFileDescriptor;
     37 import android.test.AndroidTestCase;
     38 import android.view.animation.cts.DelayedCheck;
     39 
     40 import java.io.FileNotFoundException;
     41 import java.io.IOException;
     42 import java.io.InputStream;
     43 import java.io.OutputStream;
     44 
     45 @TestTargetClass(ContentResolver.class)
     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 TABLE2_URI = Uri.parse("content://" + AUTHORITY + "/testtable2/");
     54 
     55     private static final Account ACCOUNT = new Account("cts", "cts");
     56 
     57     private static final String KEY1 = "key1";
     58     private static final String KEY2 = "key2";
     59     private static final String KEY3 = "key3";
     60     private static final int VALUE1 = 1;
     61     private static final int VALUE2 = 2;
     62     private static final int VALUE3 = 3;
     63 
     64     private static final String TEST_PACKAGE_NAME = "com.android.cts.stub";
     65 
     66     private Context mContext;
     67     private ContentResolver mContentResolver;
     68     private Cursor mCursor;
     69 
     70     @Override
     71     protected void setUp() throws Exception {
     72         super.setUp();
     73 
     74         mContext = getContext();
     75         mContentResolver = mContext.getContentResolver();
     76 
     77         // add three rows to database when every test case start.
     78         ContentValues values = new ContentValues();
     79 
     80         values.put(COLUMN_KEY_NAME, KEY1);
     81         values.put(COLUMN_VALUE_NAME, VALUE1);
     82         mContentResolver.insert(TABLE1_URI, values);
     83 
     84         values.put(COLUMN_KEY_NAME, KEY2);
     85         values.put(COLUMN_VALUE_NAME, VALUE2);
     86         mContentResolver.insert(TABLE1_URI, values);
     87 
     88         values.put(COLUMN_KEY_NAME, KEY3);
     89         values.put(COLUMN_VALUE_NAME, VALUE3);
     90         mContentResolver.insert(TABLE1_URI, values);
     91     }
     92 
     93     @Override
     94     protected void tearDown() throws Exception {
     95         mContentResolver.delete(TABLE1_URI, null, null);
     96         if ( null != mCursor && !mCursor.isClosed() ) {
     97             mCursor.close();
     98         }
     99         super.tearDown();
    100     }
    101 
    102     @TestTargetNew(
    103         level = TestLevel.COMPLETE,
    104         method = "ContentResolver",
    105         args = {android.content.Context.class}
    106     )
    107     @ToBeFixed(bug = "1695243", explanation = "Android API javadocs are incomplete")
    108     public void testConstructor() {
    109         assertNotNull(mContentResolver);
    110     }
    111 
    112     @TestTargetNew(
    113         level = TestLevel.COMPLETE,
    114         method = "getType",
    115         args = {android.net.Uri.class}
    116     )
    117     @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of " +
    118             "ContentResolver#getType(Uri) when the input Uri is null")
    119     public void testGetType() {
    120         String type1 = mContentResolver.getType(TABLE1_URI);
    121         assertTrue(type1.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0));
    122 
    123         String type2 = mContentResolver.getType(TABLE2_URI);
    124         assertTrue(type2.startsWith(ContentResolver.CURSOR_DIR_BASE_TYPE, 0));
    125 
    126         Uri invalidUri = Uri.parse("abc");
    127         assertNull(mContentResolver.getType(invalidUri));
    128 
    129         try {
    130             mContentResolver.getType(null);
    131             fail("did not throw NullPointerException when Uri is null.");
    132         } catch (NullPointerException e) {
    133             //expected.
    134         }
    135     }
    136 
    137     @TestTargetNew(
    138         level = TestLevel.COMPLETE,
    139         method = "query",
    140         args = {android.net.Uri.class, java.lang.String[].class, java.lang.String.class,
    141                 java.lang.String[].class, java.lang.String.class}
    142     )
    143     @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of " +
    144             "ContentResolver#query(Uri, String[], String, String[], String) when the input " +
    145             "param Uri is null")
    146     public void testQuery() {
    147         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    148 
    149         assertNotNull(mCursor);
    150         assertEquals(3, mCursor.getCount());
    151         assertEquals(3, mCursor.getColumnCount());
    152 
    153         mCursor.moveToLast();
    154         assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    155         assertEquals(KEY3, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    156         assertEquals(VALUE3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    157 
    158         mCursor.moveToPrevious();
    159         assertEquals(2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    160         assertEquals(KEY2, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    161         assertEquals(VALUE2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    162         mCursor.close();
    163 
    164         String selection = COLUMN_ID_NAME + "=1";
    165         mCursor = mContentResolver.query(TABLE1_URI, null, selection, null, null);
    166         assertNotNull(mCursor);
    167         assertEquals(1, mCursor.getCount());
    168         assertEquals(3, mCursor.getColumnCount());
    169 
    170         mCursor.moveToFirst();
    171         assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    172         assertEquals(KEY1, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    173         assertEquals(VALUE1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    174         mCursor.close();
    175 
    176         selection = COLUMN_KEY_NAME + "=\"" + KEY3 + "\"";
    177         mCursor = mContentResolver.query(TABLE1_URI, null, selection, null, null);
    178         assertNotNull(mCursor);
    179         assertEquals(1, mCursor.getCount());
    180         assertEquals(3, mCursor.getColumnCount());
    181 
    182         mCursor.moveToFirst();
    183         assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    184         assertEquals(KEY3, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    185         assertEquals(VALUE3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    186         mCursor.close();
    187 
    188         try {
    189             mContentResolver.query(null, null, null, null, null);
    190             fail("did not throw NullPointerException when uri is null.");
    191         } catch (NullPointerException e) {
    192             //expected.
    193         }
    194     }
    195 
    196     @TestTargetNew(
    197         level = TestLevel.COMPLETE,
    198         method = "openInputStream",
    199         args = {android.net.Uri.class}
    200     )
    201     public void testOpenInputStream() throws IOException {
    202         final Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
    203                 "://" + TEST_PACKAGE_NAME + "/" + R.drawable.pass);
    204 
    205         InputStream is = mContentResolver.openInputStream(uri);
    206         assertNotNull(is);
    207         is.close();
    208 
    209         final Uri invalidUri = Uri.parse("abc");
    210         try {
    211             mContentResolver.openInputStream(invalidUri);
    212             fail("did not throw FileNotFoundException when uri is invalid.");
    213         } catch (FileNotFoundException e) {
    214             //expected.
    215         }
    216     }
    217 
    218     @TestTargets({
    219         @TestTargetNew(
    220             level = TestLevel.COMPLETE,
    221             method = "openOutputStream",
    222             args = {android.net.Uri.class}
    223         ),
    224         @TestTargetNew(
    225             level = TestLevel.COMPLETE,
    226             method = "openOutputStream",
    227             args = {android.net.Uri.class, java.lang.String.class}
    228         )
    229     })
    230     public void testOpenOutputStream() throws IOException {
    231         Uri uri = Uri.parse(ContentResolver.SCHEME_FILE + "://" +
    232                 getContext().getCacheDir().getAbsolutePath() +
    233                 "/temp.jpg");
    234         OutputStream os = mContentResolver.openOutputStream(uri);
    235         assertNotNull(os);
    236         os.close();
    237 
    238         os = mContentResolver.openOutputStream(uri, "wa");
    239         assertNotNull(os);
    240         os.close();
    241 
    242         uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
    243                 "://" + TEST_PACKAGE_NAME + "/" + R.raw.testimage);
    244         try {
    245             mContentResolver.openOutputStream(uri);
    246             fail("did not throw FileNotFoundException when scheme is not accepted.");
    247         } catch (FileNotFoundException e) {
    248             //expected.
    249         }
    250 
    251         try {
    252             mContentResolver.openOutputStream(uri, "w");
    253             fail("did not throw FileNotFoundException when scheme is not accepted.");
    254         } catch (FileNotFoundException e) {
    255             //expected.
    256         }
    257 
    258         Uri invalidUri = Uri.parse("abc");
    259         try {
    260             mContentResolver.openOutputStream(invalidUri);
    261             fail("did not throw FileNotFoundException when uri is invalid.");
    262         } catch (FileNotFoundException e) {
    263             //expected.
    264         }
    265 
    266         try {
    267             mContentResolver.openOutputStream(invalidUri, "w");
    268             fail("did not throw FileNotFoundException when uri is invalid.");
    269         } catch (FileNotFoundException e) {
    270             //expected.
    271         }
    272     }
    273 
    274     @TestTargetNew(
    275         level = TestLevel.COMPLETE,
    276         method = "openAssetFileDescriptor",
    277         args = {android.net.Uri.class, java.lang.String.class}
    278     )
    279     public void testOpenAssetFileDescriptor() throws IOException {
    280         Uri uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
    281                 "://" + TEST_PACKAGE_NAME + "/" + R.raw.testimage);
    282 
    283         AssetFileDescriptor afd = mContentResolver.openAssetFileDescriptor(uri, "r");
    284         assertNotNull(afd);
    285         afd.close();
    286 
    287         try {
    288             mContentResolver.openAssetFileDescriptor(uri, "d");
    289             fail("did not throw FileNotFoundException when mode is unknown.");
    290         } catch (FileNotFoundException e) {
    291             //expected.
    292         }
    293 
    294         Uri invalidUri = Uri.parse("abc");
    295         try {
    296             mContentResolver.openAssetFileDescriptor(invalidUri, "r");
    297             fail("did not throw FileNotFoundException when uri is invalid.");
    298         } catch (FileNotFoundException e) {
    299             //expected.
    300         }
    301     }
    302 
    303     @TestTargetNew(
    304         level = TestLevel.COMPLETE,
    305         method = "openFileDescriptor",
    306         args = {android.net.Uri.class, java.lang.String.class}
    307     )
    308     public void testOpenFileDescriptor() throws IOException {
    309         Uri uri = Uri.parse(ContentResolver.SCHEME_FILE + "://" +
    310                 getContext().getCacheDir().getAbsolutePath() +
    311                 "/temp.jpg");
    312         ParcelFileDescriptor pfd = mContentResolver.openFileDescriptor(uri, "w");
    313         assertNotNull(pfd);
    314         pfd.close();
    315 
    316         try {
    317             mContentResolver.openFileDescriptor(uri, "d");
    318             fail("did not throw FileNotFoundException when mode is unknown.");
    319         } catch (FileNotFoundException e) {
    320             //expected.
    321         }
    322 
    323         Uri invalidUri = Uri.parse("abc");
    324         try {
    325             mContentResolver.openFileDescriptor(invalidUri, "w");
    326             fail("did not throw FileNotFoundException when uri is invalid.");
    327         } catch (FileNotFoundException e) {
    328             //expected.
    329         }
    330 
    331         uri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE +
    332                 "://" + TEST_PACKAGE_NAME + "/" + R.raw.testimage);
    333         try {
    334             mContentResolver.openFileDescriptor(uri, "w");
    335             fail("did not throw FileNotFoundException when scheme is not accepted.");
    336         } catch (FileNotFoundException e) {
    337             //expected.
    338         }
    339     }
    340 
    341     @TestTargetNew(
    342         level = TestLevel.COMPLETE,
    343         method = "insert",
    344         args = {android.net.Uri.class, android.content.ContentValues.class}
    345     )
    346     @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of " +
    347             "ContentResolver#insert(Uri, ContentValues) when the input Uri are null")
    348     public void testInsert() {
    349         String key4 = "key4";
    350         String key5 = "key5";
    351         int value4 = 4;
    352         int value5 = 5;
    353         String key4Selection = COLUMN_KEY_NAME + "=\"" + key4 + "\"";
    354 
    355         mCursor = mContentResolver.query(TABLE1_URI, null, key4Selection, null, null);
    356         assertEquals(0, mCursor.getCount());
    357         mCursor.close();
    358 
    359         ContentValues values = new ContentValues();
    360         values.put(COLUMN_KEY_NAME, key4);
    361         values.put(COLUMN_VALUE_NAME, value4);
    362         Uri uri = mContentResolver.insert(TABLE1_URI, values);
    363         assertNotNull(uri);
    364 
    365         mCursor = mContentResolver.query(TABLE1_URI, null, key4Selection, null, null);
    366         assertNotNull(mCursor);
    367         assertEquals(1, mCursor.getCount());
    368 
    369         mCursor.moveToFirst();
    370         assertEquals(4, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    371         assertEquals(key4, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    372         assertEquals(value4, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    373         mCursor.close();
    374 
    375         values.put(COLUMN_KEY_NAME, key5);
    376         values.put(COLUMN_VALUE_NAME, value5);
    377         uri = mContentResolver.insert(TABLE1_URI, values);
    378         assertNotNull(uri);
    379 
    380         // check returned uri
    381         mCursor = mContentResolver.query(uri, null, null, null, null);
    382         assertNotNull(mCursor);
    383         assertEquals(1, mCursor.getCount());
    384 
    385         mCursor.moveToLast();
    386         assertEquals(5, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    387         assertEquals(key5, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    388         assertEquals(value5, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    389         mCursor.close();
    390 
    391         try {
    392             mContentResolver.insert(null, values);
    393             fail("did not throw NullPointerException when uri is null.");
    394         } catch (NullPointerException e) {
    395             //expected.
    396         }
    397     }
    398 
    399     @TestTargetNew(
    400         level = TestLevel.COMPLETE,
    401         method = "bulkInsert",
    402         args = {android.net.Uri.class, android.content.ContentValues[].class}
    403     )
    404     @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of " +
    405             "ContentResolver#bulkInsert(Uri, ContentValues[]) when the input Uri are null")
    406     public void testBulkInsert() {
    407         String key4 = "key4";
    408         String key5 = "key5";
    409         int value4 = 4;
    410         int value5 = 5;
    411 
    412         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    413         assertNotNull(mCursor);
    414         assertEquals(3, mCursor.getCount());
    415         mCursor.close();
    416 
    417         ContentValues[] cvs = new ContentValues[2];
    418         cvs[0] = new ContentValues();
    419         cvs[0].put(COLUMN_KEY_NAME, key4);
    420         cvs[0].put(COLUMN_VALUE_NAME, value4);
    421 
    422         cvs[1] = new ContentValues();
    423         cvs[1].put(COLUMN_KEY_NAME, key5);
    424         cvs[1].put(COLUMN_VALUE_NAME, value5);
    425 
    426         assertEquals(2, mContentResolver.bulkInsert(TABLE1_URI, cvs));
    427         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    428         assertNotNull(mCursor);
    429         assertEquals(5, mCursor.getCount());
    430 
    431         mCursor.moveToLast();
    432         assertEquals(5, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    433         assertEquals(key5, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    434         assertEquals(value5, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    435 
    436         mCursor.moveToPrevious();
    437         assertEquals(4, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    438         assertEquals(key4, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    439         assertEquals(value4, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    440         mCursor.close();
    441 
    442         try {
    443             mContentResolver.bulkInsert(null, cvs);
    444             fail("did not throw NullPointerException when uri is null.");
    445         } catch (NullPointerException e) {
    446             //expected.
    447         }
    448     }
    449 
    450     @TestTargetNew(
    451         level = TestLevel.COMPLETE,
    452         method = "delete",
    453         args = {android.net.Uri.class, java.lang.String.class, java.lang.String[].class}
    454     )
    455     @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of " +
    456             "ContentResolver#delete(Uri, String, String[]) when the input Uri are null")
    457     public void testDelete() {
    458         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    459         assertNotNull(mCursor);
    460         assertEquals(3, mCursor.getCount());
    461         mCursor.close();
    462 
    463         assertEquals(3, mContentResolver.delete(TABLE1_URI, null, null));
    464         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    465         assertNotNull(mCursor);
    466         assertEquals(0, mCursor.getCount());
    467         mCursor.close();
    468 
    469         // add three rows to database.
    470         ContentValues values = new ContentValues();
    471         values.put(COLUMN_KEY_NAME, KEY1);
    472         values.put(COLUMN_VALUE_NAME, VALUE1);
    473         mContentResolver.insert(TABLE1_URI, values);
    474 
    475         values.put(COLUMN_KEY_NAME, KEY2);
    476         values.put(COLUMN_VALUE_NAME, VALUE2);
    477         mContentResolver.insert(TABLE1_URI, values);
    478 
    479         values.put(COLUMN_KEY_NAME, KEY3);
    480         values.put(COLUMN_VALUE_NAME, VALUE3);
    481         mContentResolver.insert(TABLE1_URI, values);
    482 
    483         // test delete row using selection
    484         String selection = COLUMN_ID_NAME + "=2";
    485         assertEquals(1, mContentResolver.delete(TABLE1_URI, selection, null));
    486 
    487         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    488         assertNotNull(mCursor);
    489         assertEquals(2, mCursor.getCount());
    490 
    491         mCursor.moveToFirst();
    492         assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    493         assertEquals(KEY1, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    494         assertEquals(VALUE1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    495 
    496         mCursor.moveToNext();
    497         assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    498         assertEquals(KEY3, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    499         assertEquals(VALUE3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    500         mCursor.close();
    501 
    502         selection = COLUMN_VALUE_NAME + "=3";
    503         assertEquals(1, mContentResolver.delete(TABLE1_URI, selection, null));
    504 
    505         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    506         assertNotNull(mCursor);
    507         assertEquals(1, mCursor.getCount());
    508 
    509         mCursor.moveToFirst();
    510         assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    511         assertEquals(KEY1, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    512         assertEquals(VALUE1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    513         mCursor.close();
    514 
    515         selection = COLUMN_KEY_NAME + "=\"" + KEY1 + "\"";
    516         assertEquals(1, mContentResolver.delete(TABLE1_URI, selection, null));
    517 
    518         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    519         assertNotNull(mCursor);
    520         assertEquals(0, mCursor.getCount());
    521         mCursor.close();
    522 
    523         try {
    524             mContentResolver.delete(null, null, null);
    525             fail("did not throw NullPointerException when uri is null.");
    526         } catch (NullPointerException e) {
    527             //expected.
    528         }
    529     }
    530 
    531     @TestTargetNew(
    532         level = TestLevel.COMPLETE,
    533         method = "update",
    534         args = {android.net.Uri.class, android.content.ContentValues.class,
    535                 java.lang.String.class, java.lang.String[].class}
    536     )
    537     @ToBeFixed(bug = "1695243", explanation = "The javadoc says \"return the URL of the " +
    538             "newly created row\", but actually it return an integer.")
    539     public void testUpdate() {
    540         ContentValues values = new ContentValues();
    541         String key10 = "key10";
    542         String key20 = "key20";
    543         int value10 = 10;
    544         int value20 = 20;
    545 
    546         values.put(COLUMN_KEY_NAME, key10);
    547         values.put(COLUMN_VALUE_NAME, value10);
    548 
    549         // test update all the rows.
    550         assertEquals(3, mContentResolver.update(TABLE1_URI, values, null, null));
    551         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    552         assertNotNull(mCursor);
    553         assertEquals(3, mCursor.getCount());
    554 
    555         mCursor.moveToFirst();
    556         assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    557         assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    558         assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    559 
    560         mCursor.moveToNext();
    561         assertEquals(2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    562         assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    563         assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    564 
    565         mCursor.moveToLast();
    566         assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    567         assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    568         assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    569         mCursor.close();
    570 
    571         // test update one row using selection.
    572         String selection = COLUMN_ID_NAME + "=1";
    573         values.put(COLUMN_KEY_NAME, key20);
    574         values.put(COLUMN_VALUE_NAME, value20);
    575 
    576         assertEquals(1, mContentResolver.update(TABLE1_URI, values, selection, null));
    577         mCursor = mContentResolver.query(TABLE1_URI, null, null, null, null);
    578         assertNotNull(mCursor);
    579         assertEquals(3, mCursor.getCount());
    580 
    581         mCursor.moveToFirst();
    582         assertEquals(1, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    583         assertEquals(key20, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    584         assertEquals(value20, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    585 
    586         mCursor.moveToNext();
    587         assertEquals(2, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    588         assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    589         assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    590 
    591         mCursor.moveToLast();
    592         assertEquals(3, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_ID_NAME)));
    593         assertEquals(key10, mCursor.getString(mCursor.getColumnIndexOrThrow(COLUMN_KEY_NAME)));
    594         assertEquals(value10, mCursor.getInt(mCursor.getColumnIndexOrThrow(COLUMN_VALUE_NAME)));
    595         mCursor.close();
    596 
    597         try {
    598             mContentResolver.update(null, values, null, null);
    599             fail("did not throw NullPointerException when uri is null.");
    600         } catch (NullPointerException e) {
    601             //expected.
    602         }
    603 
    604         // javadoc says it will throw NullPointerException when values are null,
    605         // but actually, it throws IllegalArgumentException here.
    606         try {
    607             mContentResolver.update(TABLE1_URI, null, null, null);
    608             fail("did not throw IllegalArgumentException when values are null.");
    609         } catch (IllegalArgumentException e) {
    610             //expected.
    611         }
    612     }
    613 
    614     @TestTargets({
    615         @TestTargetNew(
    616             level = TestLevel.COMPLETE,
    617             method = "registerContentObserver",
    618             args = {android.net.Uri.class, boolean.class, android.database.ContentObserver.class}
    619         ),
    620         @TestTargetNew(
    621             level = TestLevel.COMPLETE,
    622             method = "unregisterContentObserver",
    623             args = {android.database.ContentObserver.class}
    624         )
    625     })
    626     @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of " +
    627             "ContentResolver#registerContentObserver(Uri, boolean, ContentObserver) and " +
    628             "ContentResolver#unregisterContentObserver(ContentObserver) when the input " +
    629             "params are null")
    630     public void testRegisterContentObserver() {
    631         final MockContentObserver mco = new MockContentObserver();
    632 
    633         mContentResolver.registerContentObserver(TABLE1_URI, true, mco);
    634         assertFalse(mco.hadOnChanged());
    635 
    636         ContentValues values = new ContentValues();
    637         values.put(COLUMN_KEY_NAME, "key10");
    638         values.put(COLUMN_VALUE_NAME, 10);
    639         mContentResolver.update(TABLE1_URI, values, null, null);
    640         new DelayedCheck() {
    641             @Override
    642             protected boolean check() {
    643                 return mco.hadOnChanged();
    644             }
    645         }.run();
    646 
    647         mco.reset();
    648         mContentResolver.unregisterContentObserver(mco);
    649         assertFalse(mco.hadOnChanged());
    650         mContentResolver.update(TABLE1_URI, values, null, null);
    651 
    652         assertFalse(mco.hadOnChanged());
    653 
    654         try {
    655             mContentResolver.registerContentObserver(null, false, mco);
    656             fail("did not throw NullPointerException or IllegalArgumentException when uri is null.");
    657         } catch (NullPointerException e) {
    658             //expected.
    659         } catch (IllegalArgumentException e) {
    660             // also expected
    661         }
    662 
    663         try {
    664             mContentResolver.registerContentObserver(TABLE1_URI, false, null);
    665             fail("did not throw NullPointerException when register null content observer.");
    666         } catch (NullPointerException e) {
    667             //expected.
    668         }
    669 
    670         try {
    671             mContentResolver.unregisterContentObserver(null);
    672             fail("did not throw NullPointerException when unregister null content observer.");
    673         } catch (NullPointerException e) {
    674             //expected.
    675         }
    676     }
    677 
    678     @TestTargetNew(
    679         level = TestLevel.COMPLETE,
    680         method = "notifyChange",
    681         args = {android.net.Uri.class, android.database.ContentObserver.class}
    682     )
    683     @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of " +
    684             "ContentResolver#notifyChange(Uri, ContentObserver) when uri is null")
    685     public void testNotifyChange1() {
    686         final MockContentObserver mco = new MockContentObserver();
    687 
    688         mContentResolver.registerContentObserver(TABLE1_URI, true, mco);
    689         assertFalse(mco.hadOnChanged());
    690 
    691         mContentResolver.notifyChange(TABLE1_URI, mco);
    692         new DelayedCheck() {
    693             @Override
    694             protected boolean check() {
    695                 return mco.hadOnChanged();
    696             }
    697         }.run();
    698 
    699         mContentResolver.unregisterContentObserver(mco);
    700     }
    701 
    702     @TestTargetNew(
    703         level = TestLevel.COMPLETE,
    704         method = "notifyChange",
    705         args = {android.net.Uri.class, android.database.ContentObserver.class, boolean.class}
    706     )
    707     @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of " +
    708             "ContentResolver#notifyChange(Uri, ContentObserver, boolean) when uri is null ")
    709     public void testNotifyChange2() {
    710         final MockContentObserver mco = new MockContentObserver();
    711 
    712         mContentResolver.registerContentObserver(TABLE1_URI, true, mco);
    713         assertFalse(mco.hadOnChanged());
    714 
    715         mContentResolver.notifyChange(TABLE1_URI, mco, false);
    716         new DelayedCheck() {
    717             @Override
    718             protected boolean check() {
    719                 return mco.hadOnChanged();
    720             }
    721         }.run();
    722 
    723         mContentResolver.unregisterContentObserver(mco);
    724     }
    725 
    726     @TestTargets({
    727         @TestTargetNew(
    728             level = TestLevel.NOT_FEASIBLE,
    729             method = "startSync",
    730             args = {android.net.Uri.class, android.os.Bundle.class}
    731         ),
    732         @TestTargetNew(
    733             level = TestLevel.NOT_FEASIBLE,
    734             method = "cancelSync",
    735             args = {android.net.Uri.class}
    736         )
    737     })
    738     @ToBeFixed(bug = "1400231", explanation = "the key is SyncObserver class is deleted" +
    739             " under currently enviroment(but still exists in doc)")
    740     public void testStartCancelSync() {
    741         Bundle extras = new Bundle();
    742 
    743         extras.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true);
    744 
    745         ContentResolver.requestSync(ACCOUNT, AUTHORITY, extras);
    746         //FIXME: how to get the result to assert.
    747 
    748         ContentResolver.cancelSync(ACCOUNT, AUTHORITY);
    749         //FIXME: how to assert.
    750     }
    751 
    752     @TestTargetNew(
    753         level = TestLevel.COMPLETE,
    754         method = "startSync",
    755         args = {android.net.Uri.class, android.os.Bundle.class}
    756     )
    757     @ToBeFixed(bug = "1695243", explanation = "should add @throws clause into javadoc of " +
    758             "ContentResolver#startSync(Uri, Bundle) when extras is null")
    759     public void testStartSyncFailure() {
    760         try {
    761             ContentResolver.requestSync(null, null, null);
    762             fail("did not throw IllegalArgumentException when extras is null.");
    763         } catch (IllegalArgumentException e) {
    764             //expected.
    765         }
    766     }
    767 
    768     @TestTargetNew(
    769         level = TestLevel.COMPLETE,
    770         method = "validateSyncExtrasBundle",
    771         args = {android.os.Bundle.class}
    772     )
    773     public void testValidateSyncExtrasBundle() {
    774         Bundle extras = new Bundle();
    775         extras.putInt("Integer", 20);
    776         extras.putLong("Long", 10l);
    777         extras.putBoolean("Boolean", true);
    778         extras.putFloat("Float", 5.5f);
    779         extras.putDouble("Double", 2.5);
    780         extras.putString("String", "cts");
    781         extras.putCharSequence("CharSequence", null);
    782 
    783         ContentResolver.validateSyncExtrasBundle(extras);
    784 
    785         extras.putChar("Char", 'a'); // type Char is invalid
    786         try {
    787             ContentResolver.validateSyncExtrasBundle(extras);
    788             fail("did not throw IllegalArgumentException when extras is invalide.");
    789         } catch (IllegalArgumentException e) {
    790             //expected.
    791         }
    792     }
    793 
    794     private class MockContentObserver extends ContentObserver {
    795         private boolean mHadOnChanged = false;
    796 
    797         public MockContentObserver() {
    798             super(null);
    799         }
    800 
    801         @Override
    802         public boolean deliverSelfNotifications() {
    803             return true;
    804         }
    805 
    806         @Override
    807         public synchronized void onChange(boolean selfChange) {
    808             super.onChange(selfChange);
    809             mHadOnChanged = true;
    810         }
    811 
    812         public synchronized boolean hadOnChanged() {
    813             return mHadOnChanged;
    814         }
    815 
    816         public synchronized void reset() {
    817             mHadOnChanged = false;
    818         }
    819     }
    820 }
    821