Home | History | Annotate | Download | only in database
      1 /*
      2  * Copyright (C) 2006 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.database;
     18 
     19 import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_COLUMNNAME_INDEX;
     20 import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_DEFAULT_INDEX;
     21 import android.content.ContentValues;
     22 import android.content.Context;
     23 import android.database.sqlite.SQLiteDatabase;
     24 import android.database.sqlite.SQLiteStatement;
     25 import android.os.Handler;
     26 import android.os.Parcel;
     27 import android.test.AndroidTestCase;
     28 import android.test.PerformanceTestCase;
     29 import android.test.suitebuilder.annotation.MediumTest;
     30 import android.test.suitebuilder.annotation.SmallTest;
     31 import android.util.Log;
     32 
     33 import junit.framework.Assert;
     34 
     35 import java.io.File;
     36 import java.util.Arrays;
     37 import java.util.Locale;
     38 
     39 public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceTestCase {
     40     private static final String TAG = "DatabaseGeneralTest";
     41 
     42     private static final String sString1 = "this is a test";
     43     private static final String sString2 = "and yet another test";
     44     private static final String sString3 = "this string is a little longer, but still a test";
     45     private static final String PHONE_NUMBER = "16175551212";
     46 
     47     private static final int CURRENT_DATABASE_VERSION = 42;
     48     private SQLiteDatabase mDatabase;
     49     private File mDatabaseFile;
     50 
     51     @Override
     52     protected void setUp() throws Exception {
     53         super.setUp();
     54         File dbDir = getContext().getDir(this.getClass().getName(), Context.MODE_PRIVATE);
     55         mDatabaseFile = new File(dbDir, "database_test.db");
     56         if (mDatabaseFile.exists()) {
     57             mDatabaseFile.delete();
     58         }
     59         mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null);
     60         assertNotNull(mDatabase);
     61         mDatabase.setVersion(CURRENT_DATABASE_VERSION);
     62     }
     63 
     64     @Override
     65     protected void tearDown() throws Exception {
     66         mDatabase.close();
     67         mDatabaseFile.delete();
     68         super.tearDown();
     69     }
     70 
     71     public boolean isPerformanceOnly() {
     72         return false;
     73     }
     74 
     75     // These test can only be run once.
     76     public int startPerformance(Intermediates intermediates) {
     77         return 1;
     78     }
     79 
     80     private void populateDefaultTable() {
     81         mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
     82 
     83         mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');");
     84         mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');");
     85         mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');");
     86     }
     87 
     88     @MediumTest
     89     public void testVersion() throws Exception {
     90         assertEquals(CURRENT_DATABASE_VERSION, mDatabase.getVersion());
     91         mDatabase.setVersion(11);
     92         assertEquals(11, mDatabase.getVersion());
     93     }
     94 
     95     @MediumTest
     96     public void testUpdate() throws Exception {
     97         populateDefaultTable();
     98 
     99         ContentValues values = new ContentValues(1);
    100         values.put("data", "this is an updated test");
    101         assertEquals(1, mDatabase.update("test", values, "_id=1", null));
    102         Cursor c = mDatabase.query("test", null, "_id=1", null, null, null, null);
    103         assertNotNull(c);
    104         assertEquals(1, c.getCount());
    105         c.moveToFirst();
    106         String value = c.getString(c.getColumnIndexOrThrow("data"));
    107         assertEquals("this is an updated test", value);
    108     }
    109 
    110     @MediumTest
    111     public void testPhoneNumbersEqual() throws Exception {
    112         mDatabase.execSQL("CREATE TABLE phones (num TEXT);");
    113         mDatabase.execSQL("INSERT INTO phones (num) VALUES ('911');");
    114         mDatabase.execSQL("INSERT INTO phones (num) VALUES ('5555');");
    115         mDatabase.execSQL("INSERT INTO phones (num) VALUES ('+" + PHONE_NUMBER + "');");
    116 
    117         String number;
    118         Cursor c;
    119 
    120         c = mDatabase.query("phones", null,
    121                 "PHONE_NUMBERS_EQUAL(num, '504-555-7683')", null, null, null, null);
    122         assertTrue(c == null || c.getCount() == 0);
    123         c.close();
    124 
    125         c = mDatabase.query("phones", null,
    126                 "PHONE_NUMBERS_EQUAL(num, '911')", null, null, null, null);
    127         assertNotNull(c);
    128         assertEquals(1, c.getCount());
    129         c.moveToFirst();
    130         number = c.getString(c.getColumnIndexOrThrow("num"));
    131         assertEquals("911", number);
    132         c.close();
    133 
    134         c = mDatabase.query("phones", null,
    135                 "PHONE_NUMBERS_EQUAL(num, '5555')", null, null, null, null);
    136         assertNotNull(c);
    137         assertEquals(1, c.getCount());
    138         c.moveToFirst();
    139         number = c.getString(c.getColumnIndexOrThrow("num"));
    140         assertEquals("5555", number);
    141         c.close();
    142 
    143         c = mDatabase.query("phones", null,
    144                 "PHONE_NUMBERS_EQUAL(num, '180055555555')", null, null, null, null);
    145         assertTrue(c == null || c.getCount() == 0);
    146         c.close();
    147 
    148         c = mDatabase.query("phones", null,
    149                 "PHONE_NUMBERS_EQUAL(num, '+" + PHONE_NUMBER + "')", null, null, null, null);
    150         assertNotNull(c);
    151         assertEquals(1, c.getCount());
    152         c.moveToFirst();
    153         number = c.getString(c.getColumnIndexOrThrow("num"));
    154         assertEquals("+" + PHONE_NUMBER, number);
    155         c.close();
    156 
    157         c = mDatabase.query("phones", null,
    158                 "PHONE_NUMBERS_EQUAL(num, '+1 (617).555-1212')", null, null, null, null);
    159         assertNotNull(c);
    160         assertEquals(1, c.getCount());
    161         c.moveToFirst();
    162         number = c.getString(c.getColumnIndexOrThrow("num"));
    163         assertEquals("+" + PHONE_NUMBER, number);
    164         c.close();
    165 
    166         c = mDatabase.query("phones", null,
    167                 "PHONE_NUMBERS_EQUAL(num, '" + PHONE_NUMBER + "')", null, null, null, null);
    168         assertNotNull(c);
    169         assertEquals(1, c.getCount());
    170         c.moveToFirst();
    171         number = c.getString(c.getColumnIndexOrThrow("num"));
    172         assertEquals("+" + PHONE_NUMBER, number);
    173         c.close();
    174 
    175         /*
    176         c = mDatabase.query("phones", null,
    177                 "PHONE_NUMBERS_EQUAL(num, '5551212')", null, null, null, null);
    178         assertNotNull(c);
    179         assertEquals(1, c.getCount());
    180         c.moveToFirst();
    181         number = c.getString(c.getColumnIndexOrThrow("num"));
    182         assertEquals("+" + PHONE_NUMBER, number);
    183         c.close();
    184         */
    185 
    186         c = mDatabase.query("phones", null,
    187                 "PHONE_NUMBERS_EQUAL(num, '011" + PHONE_NUMBER + "')", null, null, null, null);
    188         assertNotNull(c);
    189         assertEquals(1, c.getCount());
    190         c.moveToFirst();
    191         number = c.getString(c.getColumnIndexOrThrow("num"));
    192         assertEquals("+" + PHONE_NUMBER, number);
    193         c.close();
    194 
    195         c = mDatabase.query("phones", null,
    196                 "PHONE_NUMBERS_EQUAL(num, '00" + PHONE_NUMBER + "')", null, null, null, null);
    197         assertNotNull(c);
    198         assertEquals(1, c.getCount());
    199         c.moveToFirst();
    200         number = c.getString(c.getColumnIndexOrThrow("num"));
    201         assertEquals("+" + PHONE_NUMBER, number);
    202         c.close();
    203     }
    204 
    205     private void phoneNumberCompare(String phone1, String phone2, boolean equal,
    206             boolean useStrictComparation) {
    207         String[] temporalPhoneNumbers = new String[2];
    208         temporalPhoneNumbers[0] = phone1;
    209         temporalPhoneNumbers[1] = phone2;
    210 
    211         Cursor cursor = mDatabase.rawQuery(
    212                 String.format(
    213                         "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?, %d) " +
    214                         "THEN 'equal' ELSE 'not equal' END",
    215                         (useStrictComparation ? 1 : 0)),
    216                 temporalPhoneNumbers);
    217         try {
    218             assertNotNull(cursor);
    219             assertTrue(cursor.moveToFirst());
    220             if (equal) {
    221                 assertEquals(String.format("Unexpectedly, \"%s != %s\".", phone1, phone2),
    222                         "equal", cursor.getString(0));
    223             } else {
    224                 assertEquals(String.format("Unexpectedly, \"%s\" == \"%s\".", phone1, phone2),
    225                         "not equal", cursor.getString(0));
    226             }
    227         } finally {
    228             if (cursor != null) {
    229                 cursor.close();
    230             }
    231         }
    232     }
    233 
    234     private void assertPhoneNumberEqual(String phone1, String phone2) throws Exception {
    235         assertPhoneNumberEqual(phone1, phone2, true);
    236         assertPhoneNumberEqual(phone1, phone2, false);
    237     }
    238 
    239     private void assertPhoneNumberEqual(String phone1, String phone2, boolean useStrict)
    240             throws Exception {
    241         phoneNumberCompare(phone1, phone2, true, useStrict);
    242     }
    243 
    244     private void assertPhoneNumberNotEqual(String phone1, String phone2) throws Exception {
    245         assertPhoneNumberNotEqual(phone1, phone2, true);
    246         assertPhoneNumberNotEqual(phone1, phone2, false);
    247     }
    248 
    249     private void assertPhoneNumberNotEqual(String phone1, String phone2, boolean useStrict)
    250             throws Exception {
    251         phoneNumberCompare(phone1, phone2, false, useStrict);
    252     }
    253 
    254     /**
    255      * Tests international matching issues for the PHONE_NUMBERS_EQUAL function.
    256      *
    257      * @throws Exception
    258      */
    259     @SmallTest
    260     public void testPhoneNumbersEqualInternationl() throws Exception {
    261         assertPhoneNumberEqual("1", "1");
    262         assertPhoneNumberEqual("123123", "123123");
    263         assertPhoneNumberNotEqual("123123", "923123");
    264         assertPhoneNumberNotEqual("123123", "123129");
    265         assertPhoneNumberNotEqual("123123", "1231234");
    266         assertPhoneNumberNotEqual("123123", "0123123", false);
    267         assertPhoneNumberNotEqual("123123", "0123123", true);
    268         assertPhoneNumberEqual("650-253-0000", "6502530000");
    269         assertPhoneNumberEqual("650-253-0000", "650 253 0000");
    270         assertPhoneNumberEqual("650 253 0000", "6502530000");
    271         assertPhoneNumberEqual("+1 650-253-0000", "6502530000");
    272         assertPhoneNumberEqual("001 650-253-0000", "6502530000");
    273         assertPhoneNumberEqual("0111 650-253-0000", "6502530000");
    274 
    275         // Russian trunk digit
    276         assertPhoneNumberEqual("+79161234567", "89161234567");
    277 
    278         // French trunk digit
    279         assertPhoneNumberEqual("+33123456789", "0123456789");
    280 
    281         // Trunk digit for city codes in the Netherlands
    282         assertPhoneNumberEqual("+31771234567", "0771234567");
    283 
    284         // Test broken caller ID seen on call from Thailand to the US
    285         assertPhoneNumberEqual("+66811234567", "166811234567");
    286 
    287         // Test the same in-country number with different country codes
    288         assertPhoneNumberNotEqual("+33123456789", "+1123456789");
    289 
    290         // Test one number with country code and the other without
    291         assertPhoneNumberEqual("5125551212", "+15125551212");
    292 
    293         // Test two NANP numbers that only differ in the area code
    294         assertPhoneNumberNotEqual("5125551212", "6505551212");
    295 
    296         // Japanese phone numbers
    297         assertPhoneNumberEqual("090-1234-5678", "+819012345678");
    298         assertPhoneNumberEqual("090(1234)5678", "+819012345678");
    299         assertPhoneNumberEqual("090-1234-5678", "+81-90-1234-5678");
    300 
    301         // Equador
    302         assertPhoneNumberEqual("+593(800)123-1234", "8001231234");
    303         assertPhoneNumberEqual("+593-2-1234-123", "21234123");
    304 
    305         // Two continuous 0 at the beginning of the phone string should not be
    306         // treated as trunk prefix in the strict comparation.
    307         assertPhoneNumberEqual("008001231234", "8001231234", false);
    308         assertPhoneNumberNotEqual("008001231234", "8001231234", true);
    309 
    310         // Confirm that the bug found before does not re-appear in the strict compalation
    311         assertPhoneNumberEqual("080-1234-5678", "+819012345678", false);
    312         assertPhoneNumberNotEqual("080-1234-5678", "+819012345678", true);
    313     }
    314 
    315     @MediumTest
    316     public void testCopyString() throws Exception {
    317         mDatabase.execSQL("CREATE TABLE guess (numi INTEGER, numf FLOAT, str TEXT);");
    318         mDatabase.execSQL(
    319                 "INSERT INTO guess (numi,numf,str) VALUES (0,0.0,'ZoomZoomZoomZoom');");
    320         mDatabase.execSQL("INSERT INTO guess (numi,numf,str) VALUES (2000000000,3.1415926535,'');");
    321         String chinese = "\u4eac\u4ec5 \u5c3d\u5f84\u60ca";
    322         String[] arr = new String[1];
    323         arr[0] = chinese;
    324         mDatabase.execSQL("INSERT INTO guess (numi,numf,str) VALUES (-32768,-1.0,?)", arr);
    325 
    326         Cursor c;
    327 
    328         c = mDatabase.rawQuery("SELECT * FROM guess", null);
    329 
    330         c.moveToFirst();
    331 
    332         CharArrayBuffer buf = new CharArrayBuffer(14);
    333 
    334         String compareTo = c.getString(c.getColumnIndexOrThrow("numi"));
    335         int numiIdx = c.getColumnIndexOrThrow("numi");
    336         int numfIdx = c.getColumnIndexOrThrow("numf");
    337         int strIdx = c.getColumnIndexOrThrow("str");
    338 
    339         c.copyStringToBuffer(numiIdx, buf);
    340         assertEquals(1, buf.sizeCopied);
    341         assertEquals(compareTo, new String(buf.data, 0, buf.sizeCopied));
    342 
    343         c.copyStringToBuffer(strIdx, buf);
    344         assertEquals("ZoomZoomZoomZoom", new String(buf.data, 0, buf.sizeCopied));
    345 
    346         c.moveToNext();
    347         compareTo = c.getString(numfIdx);
    348 
    349         c.copyStringToBuffer(numfIdx, buf);
    350         assertEquals(compareTo, new String(buf.data, 0, buf.sizeCopied));
    351         c.copyStringToBuffer(strIdx, buf);
    352         assertEquals(0, buf.sizeCopied);
    353 
    354         c.moveToNext();
    355         c.copyStringToBuffer(numfIdx, buf);
    356         assertEquals(-1.0, Double.valueOf(
    357                 new String(buf.data, 0, buf.sizeCopied)).doubleValue());
    358 
    359         c.copyStringToBuffer(strIdx, buf);
    360         compareTo = c.getString(strIdx);
    361         assertEquals(chinese, compareTo);
    362 
    363         assertEquals(chinese, new String(buf.data, 0, buf.sizeCopied));
    364         c.close();
    365     }
    366 
    367     @MediumTest
    368     public void testSchemaChange1() throws Exception {
    369         SQLiteDatabase db1 = mDatabase;
    370         Cursor cursor;
    371 
    372         db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);");
    373 
    374         cursor = db1.query("db1", null, null, null, null, null, null);
    375         assertNotNull("Cursor is null", cursor);
    376 
    377         db1.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);");
    378 
    379         assertEquals(0, cursor.getCount());
    380         cursor.deactivate();
    381     }
    382 
    383     @MediumTest
    384     public void testSchemaChange2() throws Exception {
    385         SQLiteDatabase db1 = mDatabase;
    386         SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile, null);
    387         Cursor cursor;
    388 
    389         db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);");
    390 
    391         cursor = db1.query("db1", null, null, null, null, null, null);
    392         assertNotNull("Cursor is null", cursor);
    393         assertEquals(0, cursor.getCount());
    394         cursor.deactivate();
    395         // this cause exception because we're still using sqlite_prepate16 and not
    396         // sqlite_prepare16_v2. The v2 variant added the ability to check the
    397         // schema version and handle the case when the schema has changed
    398         // Marco Nelissen claim it was 2x slower to compile SQL statements so
    399         // I reverted back to the v1 variant.
    400         /* db2.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);");
    401 
    402         cursor = db1.query("db1", null, null, null, null, null, null);
    403         assertNotNull("Cursor is null", cursor);
    404         assertEquals(0, cursor.count());
    405         cursor.deactivate();
    406         */
    407     }
    408 
    409     @MediumTest
    410     public void testSchemaChange3() throws Exception {
    411         SQLiteDatabase db1 = mDatabase;
    412         SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile, null);
    413         Cursor cursor;
    414 
    415 
    416         db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);");
    417         db1.execSQL("INSERT INTO db1 (data) VALUES ('test');");
    418 
    419         cursor = db1.query("db1", null, null, null, null, null, null);
    420         // this cause exception because we're still using sqlite_prepate16 and not
    421         // sqlite_prepare16_v2. The v2 variant added the ability to check the
    422         // schema version and handle the case when the schema has changed
    423         // Marco Nelissen claim it was 2x slower to compile SQL statements so
    424         // I reverted back to the v1 variant.
    425         /* db2.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);");
    426 
    427         assertNotNull("Cursor is null", cursor);
    428         assertEquals(1, cursor.count());
    429         assertTrue(cursor.first());
    430         assertEquals("test", cursor.getString(cursor.getColumnIndexOrThrow("data")));
    431         cursor.deactivate();
    432         */
    433     }
    434 
    435     private class ChangeObserver extends ContentObserver {
    436         private int mCursorNotificationCount = 0;
    437         private int mNotificationCount = 0;
    438 
    439         public int getCursorNotificationCount() {
    440             return mCursorNotificationCount;
    441         }
    442 
    443         public int getNotificationCount() {
    444             return mNotificationCount;
    445         }
    446 
    447         public ChangeObserver(boolean cursor) {
    448             super(new Handler());
    449             mCursor = cursor;
    450         }
    451 
    452         @Override
    453         public boolean deliverSelfNotifications() {
    454             return true;
    455         }
    456 
    457         @Override
    458         public void onChange(boolean selfChange) {
    459             if (mCursor) {
    460                 mCursorNotificationCount++;
    461             } else {
    462                 mNotificationCount++;
    463             }
    464         }
    465 
    466         boolean mCursor;
    467     }
    468 
    469     @MediumTest
    470     public void testNotificationTest1() throws Exception {
    471         /*
    472         Cursor c = mContentResolver.query(Notes.CONTENT_URI,
    473                 new String[] {Notes._ID, Notes.NOTE},
    474                 null, null);
    475         c.registerContentObserver(new MyContentObserver(true));
    476         int count = c.count();
    477 
    478         MyContentObserver observer = new MyContentObserver(false);
    479         mContentResolver.registerContentObserver(Notes.CONTENT_URI, true, observer);
    480 
    481         Uri uri;
    482 
    483         HashMap<String, String> values = new HashMap<String, String>();
    484         values.put(Notes.NOTE, "test note1");
    485         uri = mContentResolver.insert(Notes.CONTENT_URI, values);
    486         assertEquals(1, mCursorNotificationCount);
    487         assertEquals(1, mNotificationCount);
    488 
    489         c.requery();
    490         assertEquals(count + 1, c.count());
    491         c.first();
    492         assertEquals("test note1", c.getString(c.getColumnIndex(Notes.NOTE)));
    493         c.updateString(c.getColumnIndex(Notes.NOTE), "test note2");
    494         c.commitUpdates();
    495 
    496         assertEquals(2, mCursorNotificationCount);
    497         assertEquals(2, mNotificationCount);
    498 
    499         mContentResolver.delete(uri, null);
    500 
    501         assertEquals(3, mCursorNotificationCount);
    502         assertEquals(3, mNotificationCount);
    503 
    504         mContentResolver.unregisterContentObserver(observer);
    505         */
    506     }
    507 
    508     @MediumTest
    509     public void testSelectionArgs() throws Exception {
    510         mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);");
    511         ContentValues values = new ContentValues(1);
    512         values.put("data", "don't forget to handled 's");
    513         mDatabase.insert("test", "data", values);
    514         values.clear();
    515         values.put("data", "no apostrophes here");
    516         mDatabase.insert("test", "data", values);
    517         Cursor c = mDatabase.query(
    518                 "test", null, "data GLOB ?", new String[]{"*'*"}, null, null, null);
    519         assertEquals(1, c.getCount());
    520         assertTrue(c.moveToFirst());
    521         assertEquals("don't forget to handled 's", c.getString(1));
    522         c.deactivate();
    523 
    524         // make sure code should checking null string properly so that
    525         // it won't crash
    526         try {
    527             mDatabase.query("test", new String[]{"_id"},
    528                     "_id=?", new String[]{null}, null, null, null);
    529             fail("expected exception not thrown");
    530         } catch (IllegalArgumentException e) {
    531             // expected
    532         }
    533     }
    534 
    535     @MediumTest
    536     public void testTokenize() throws Exception {
    537         Cursor c;
    538         mDatabase.execSQL("CREATE TABLE tokens (" +
    539                 "token TEXT COLLATE unicode," +
    540                 "source INTEGER," +
    541                 "token_index INTEGER," +
    542                 "tag TEXT" +
    543                 ");");
    544         mDatabase.execSQL("CREATE TABLE tokens_no_index (" +
    545                 "token TEXT COLLATE unicode," +
    546                 "source INTEGER" +
    547                 ");");
    548 
    549         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    550                 "SELECT _TOKENIZE(NULL, NULL, NULL, NULL)", null));
    551         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    552                 "SELECT _TOKENIZE('tokens', NULL, NULL, NULL)", null));
    553         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    554                 "SELECT _TOKENIZE('tokens', 10, NULL, NULL)", null));
    555         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    556                 "SELECT _TOKENIZE('tokens', 10, 'some string', NULL)", null));
    557 
    558         Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase,
    559                 "SELECT _TOKENIZE('tokens', 11, 'some string ok', ' ', 1, 'foo')", null));
    560         Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
    561                 "SELECT _TOKENIZE('tokens', 11, 'second field', ' ', 1, 'bar')", null));
    562 
    563         Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase,
    564                 "SELECT _TOKENIZE('tokens_no_index', 20, 'some string ok', ' ')", null));
    565         Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase,
    566                 "SELECT _TOKENIZE('tokens_no_index', 21, 'foo bar baz', ' ', 0)", null));
    567 
    568         // test Chinese
    569         String chinese = new String("\u4eac\u4ec5 \u5c3d\u5f84\u60ca");
    570         Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
    571                 "SELECT _TOKENIZE('tokens', 12,'" + chinese + "', ' ', 1)", null));
    572 
    573         String icustr = new String("Fr\u00e9d\u00e9ric Hj\u00f8nnev\u00e5g");
    574 
    575         Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
    576                 "SELECT _TOKENIZE('tokens', 13, '" + icustr + "', ' ', 1)", null));
    577 
    578         Assert.assertEquals(9, DatabaseUtils.longForQuery(mDatabase,
    579                 "SELECT count(*) from tokens;", null));
    580 
    581         String key = DatabaseUtils.getHexCollationKey("Frederic Hjonneva");
    582         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    583                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    584         Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase,
    585                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    586         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    587                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    588         key = DatabaseUtils.getHexCollationKey("Hjonneva");
    589         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    590                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    591         Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase,
    592                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    593         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    594                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    595 
    596         key = DatabaseUtils.getHexCollationKey("some string ok");
    597         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    598                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    599         Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
    600                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    601         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    602                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    603         Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase,
    604                 "SELECT tag from tokens where token GLOB '" + key + "*'", null));
    605         key = DatabaseUtils.getHexCollationKey("string");
    606         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    607                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    608         Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
    609                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    610         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    611                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    612         Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase,
    613                 "SELECT tag from tokens where token GLOB '" + key + "*'", null));
    614         key = DatabaseUtils.getHexCollationKey("ok");
    615         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    616                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    617         Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
    618                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    619         Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase,
    620                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    621         Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase,
    622                 "SELECT tag from tokens where token GLOB '" + key + "*'", null));
    623 
    624         key = DatabaseUtils.getHexCollationKey("second field");
    625         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    626                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    627         Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
    628                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    629         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    630                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    631         Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase,
    632                 "SELECT tag from tokens where token GLOB '" + key + "*'", null));
    633         key = DatabaseUtils.getHexCollationKey("field");
    634         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    635                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    636         Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase,
    637                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    638         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    639                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    640         Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase,
    641                 "SELECT tag from tokens where token GLOB '" + key + "*'", null));
    642 
    643         key = DatabaseUtils.getHexCollationKey(chinese);
    644         String[] a = new String[1];
    645         a[0] = key;
    646         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    647                 "SELECT count(*) from tokens where token= ?", a));
    648         Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
    649                 "SELECT source from tokens where token= ?", a));
    650         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    651                 "SELECT token_index from tokens where token= ?", a));
    652         a[0] += "*";
    653         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    654              "SELECT count(*) from tokens where token GLOB ?", a));
    655         Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
    656                 "SELECT source from tokens where token GLOB ?", a));
    657         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    658                 "SELECT token_index from tokens where token GLOB ?", a));
    659 
    660        Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    661                 "SELECT count(*) from tokens where token= '" + key + "'", null));
    662        Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
    663                "SELECT source from tokens where token= '" + key + "'", null));
    664        Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    665                "SELECT token_index from tokens where token= '" + key + "'", null));
    666 
    667         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    668                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    669         Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
    670                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    671         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    672                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    673 
    674         key = DatabaseUtils.getHexCollationKey("\u4eac\u4ec5");
    675         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    676                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    677         Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
    678                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    679         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    680                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    681 
    682         key = DatabaseUtils.getHexCollationKey("\u5c3d\u5f84\u60ca");
    683         Log.d("DatabaseGeneralTest", "key = " + key);
    684         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    685                 "SELECT count(*) from tokens where token GLOB '" + key + "*'", null));
    686         Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase,
    687                 "SELECT source from tokens where token GLOB '" + key + "*'", null));
    688         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    689                 "SELECT token_index from tokens where token GLOB '" + key + "*'", null));
    690 
    691         Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase,
    692                 "SELECT count(*) from tokens where token GLOB 'ab*'", null));
    693 
    694         key = DatabaseUtils.getHexCollationKey("some string ok");
    695         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    696                 "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null));
    697         Assert.assertEquals(20, DatabaseUtils.longForQuery(mDatabase,
    698                 "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null));
    699 
    700         key = DatabaseUtils.getHexCollationKey("bar");
    701         Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase,
    702                 "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null));
    703         Assert.assertEquals(21, DatabaseUtils.longForQuery(mDatabase,
    704                 "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null));
    705     }
    706 
    707     @MediumTest
    708     public void testTransactions() throws Exception {
    709         mDatabase.execSQL("CREATE TABLE test (num INTEGER);");
    710         mDatabase.execSQL("INSERT INTO test (num) VALUES (0)");
    711 
    712         // Make sure that things work outside an explicit transaction.
    713         setNum(1);
    714         checkNum(1);
    715 
    716         // Test a single-level transaction.
    717         setNum(0);
    718         mDatabase.beginTransaction();
    719         setNum(1);
    720         mDatabase.setTransactionSuccessful();
    721         mDatabase.endTransaction();
    722         checkNum(1);
    723         Assert.assertFalse(mDatabase.isDbLockedByCurrentThread());
    724 
    725         // Test a rolled-back transaction.
    726         setNum(0);
    727         mDatabase.beginTransaction();
    728         setNum(1);
    729         mDatabase.endTransaction();
    730         checkNum(0);
    731         Assert.assertFalse(mDatabase.isDbLockedByCurrentThread());
    732 
    733         // We should get an error if we end a non-existent transaction.
    734         assertThrowsIllegalState(new Runnable() { public void run() {
    735             mDatabase.endTransaction();
    736         }});
    737 
    738         // We should get an error if a set a non-existent transaction as clean.
    739         assertThrowsIllegalState(new Runnable() { public void run() {
    740             mDatabase.setTransactionSuccessful();
    741         }});
    742 
    743         mDatabase.beginTransaction();
    744         mDatabase.setTransactionSuccessful();
    745         // We should get an error if we mark a transaction as clean twice.
    746         assertThrowsIllegalState(new Runnable() { public void run() {
    747             mDatabase.setTransactionSuccessful();
    748         }});
    749         // We should get an error if we begin a transaction after marking the parent as clean.
    750         assertThrowsIllegalState(new Runnable() { public void run() {
    751             mDatabase.beginTransaction();
    752         }});
    753         mDatabase.endTransaction();
    754         Assert.assertFalse(mDatabase.isDbLockedByCurrentThread());
    755 
    756         // Test a two-level transaction.
    757         setNum(0);
    758         mDatabase.beginTransaction();
    759         mDatabase.beginTransaction();
    760         setNum(1);
    761         mDatabase.setTransactionSuccessful();
    762         mDatabase.endTransaction();
    763         mDatabase.setTransactionSuccessful();
    764         mDatabase.endTransaction();
    765         checkNum(1);
    766         Assert.assertFalse(mDatabase.isDbLockedByCurrentThread());
    767 
    768         // Test rolling back an inner transaction.
    769         setNum(0);
    770         mDatabase.beginTransaction();
    771         mDatabase.beginTransaction();
    772         setNum(1);
    773         mDatabase.endTransaction();
    774         mDatabase.setTransactionSuccessful();
    775         mDatabase.endTransaction();
    776         checkNum(0);
    777         Assert.assertFalse(mDatabase.isDbLockedByCurrentThread());
    778 
    779         // Test rolling back an outer transaction.
    780         setNum(0);
    781         mDatabase.beginTransaction();
    782         mDatabase.beginTransaction();
    783         setNum(1);
    784         mDatabase.setTransactionSuccessful();
    785         mDatabase.endTransaction();
    786         mDatabase.endTransaction();
    787         checkNum(0);
    788         Assert.assertFalse(mDatabase.isDbLockedByCurrentThread());
    789     }
    790 
    791     private void setNum(int num) {
    792         mDatabase.execSQL("UPDATE test SET num = " + num);
    793     }
    794 
    795     private void checkNum(int num) {
    796         Assert.assertEquals(
    797                 num, DatabaseUtils.longForQuery(mDatabase, "SELECT num FROM test", null));
    798     }
    799 
    800     private void assertThrowsIllegalState(Runnable r) {
    801         boolean ok = false;
    802         try {
    803             r.run();
    804         } catch (IllegalStateException e) {
    805             ok = true;
    806         }
    807         Assert.assertTrue(ok);
    808     }
    809 
    810     // Disable these until we can explicitly mark them as stress tests
    811     public void xxtestMem1() throws Exception {
    812         populateDefaultTable();
    813 
    814         for (int i = 0; i < 50000; i++) {
    815             Cursor cursor = mDatabase.query("test", null, null, null, null, null, null);
    816             cursor.moveToFirst();
    817             cursor.close();
    818 //                Log.i("~~~~", "Finished round " + i);
    819         }
    820     }
    821 
    822     // Disable these until we can explicitly mark them as stress tests
    823     public void xxtestMem2() throws Exception {
    824         populateDefaultTable();
    825 
    826         for (int i = 0; i < 50000; i++) {
    827             Cursor cursor = mDatabase.query("test", null, null, null, null, null, null);
    828             cursor.close();
    829 //                Log.i("~~~~", "Finished round " + i);
    830         }
    831     }
    832 
    833     // Disable these until we can explicitly mark them as stress tests
    834     public void xxtestMem3() throws Exception {
    835         populateDefaultTable();
    836 
    837         for (int i = 0; i < 50000; i++) {
    838             Cursor cursor = mDatabase.query("test", null, null, null, null, null, null);
    839             cursor.deactivate();
    840 //                Log.i("~~~~", "Finished round " + i);
    841         }
    842     }
    843 
    844     @MediumTest
    845     public void testContentValues() throws Exception {
    846         ContentValues values = new ContentValues();
    847         values.put("string", "value");
    848         assertEquals("value", values.getAsString("string"));
    849         byte[] bytes = new byte[42];
    850         Arrays.fill(bytes, (byte) 0x28);
    851         values.put("byteArray", bytes);
    852         assertTrue(Arrays.equals(bytes, values.getAsByteArray("byteArray")));
    853 
    854         // Write the ContentValues to a Parcel and then read them out
    855         Parcel p = Parcel.obtain();
    856         values.writeToParcel(p, 0);
    857         p.setDataPosition(0);
    858         values = ContentValues.CREATOR.createFromParcel(p);
    859 
    860         // Read the values out again and make sure they're the same
    861         assertTrue(Arrays.equals(bytes, values.getAsByteArray("byteArray")));
    862         assertEquals("value", values.get("string"));
    863     }
    864 
    865     @MediumTest
    866     public void testTableInfoPragma() throws Exception {
    867         mDatabase.execSQL("CREATE TABLE pragma_test (" +
    868                 "i INTEGER DEFAULT 1234, " +
    869                 "j INTEGER, " +
    870                 "s TEXT DEFAULT 'hello', " +
    871                 "t TEXT, " +
    872                 "'select' TEXT DEFAULT \"hello\")");
    873         try {
    874             Cursor cur = mDatabase.rawQuery("PRAGMA table_info(pragma_test)", null);
    875             Assert.assertEquals(5, cur.getCount());
    876 
    877             Assert.assertTrue(cur.moveToNext());
    878             Assert.assertEquals("i",
    879                     cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX));
    880             Assert.assertEquals("1234",
    881                     cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX));
    882 
    883             Assert.assertTrue(cur.moveToNext());
    884             Assert.assertEquals("j",
    885                     cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX));
    886             Assert.assertNull(cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX));
    887 
    888             Assert.assertTrue(cur.moveToNext());
    889             Assert.assertEquals("s",
    890                     cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX));
    891             Assert.assertEquals("'hello'",
    892                     cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX));
    893 
    894             Assert.assertTrue(cur.moveToNext());
    895             Assert.assertEquals("t",
    896                     cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX));
    897             Assert.assertNull(cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX));
    898 
    899             Assert.assertTrue(cur.moveToNext());
    900             Assert.assertEquals("select",
    901                     cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX));
    902             Assert.assertEquals("\"hello\"",
    903                     cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX));
    904 
    905             cur.close();
    906         } catch (Throwable t) {
    907             throw new RuntimeException(
    908                     "If you see this test fail, it's likely that something about " +
    909                     "sqlite's PRAGMA table_info(...) command has changed.", t);
    910         }
    911     }
    912 
    913     @MediumTest
    914     public void testInsertHelper() throws Exception {
    915         Cursor cur;
    916         ContentValues cv;
    917         long row;
    918 
    919         mDatabase.execSQL("CREATE TABLE insert_test (" +
    920                 "_id INTEGER PRIMARY KEY, " +
    921                 "s TEXT NOT NULL UNIQUE, " +
    922                 "t TEXT NOT NULL DEFAULT 'hello world', " +
    923                 "i INTEGER, " +
    924                 "j INTEGER NOT NULL DEFAULT 1234, " +
    925                 "'select' TEXT)");
    926 
    927         DatabaseUtils.InsertHelper ih =
    928             new DatabaseUtils.InsertHelper(mDatabase, "insert_test");
    929 
    930         cv = new ContentValues();
    931         cv.put("s", "one");
    932         row = ih.insert(cv);
    933         cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null);
    934         Assert.assertTrue(cur.moveToFirst());
    935         Assert.assertEquals("one", cur.getString(1));
    936         Assert.assertEquals("hello world", cur.getString(2));
    937         Assert.assertNull(cur.getString(3));
    938         Assert.assertEquals(1234, cur.getLong(4));
    939         Assert.assertNull(cur.getString(5));
    940         cur.close();
    941 
    942         cv = new ContentValues();
    943         cv.put("s", "two");
    944         cv.put("t", "goodbye world");
    945         row = ih.insert(cv);
    946         cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null);
    947         Assert.assertTrue(cur.moveToFirst());
    948         Assert.assertEquals("two", cur.getString(1));
    949         Assert.assertEquals("goodbye world", cur.getString(2));
    950         Assert.assertNull(cur.getString(3));
    951         Assert.assertEquals(1234, cur.getLong(4));
    952         Assert.assertNull(cur.getString(5));
    953         cur.close();
    954 
    955         cv = new ContentValues();
    956         cv.put("t", "goodbye world");
    957         row = ih.insert(cv);
    958         Assert.assertEquals(-1, row);
    959 
    960         cv = new ContentValues();
    961         cv.put("s", "three");
    962         cv.put("i", 2345);
    963         cv.put("j", 3456);
    964         cv.put("select", "tricky");
    965         row = ih.insert(cv);
    966         cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null);
    967         Assert.assertTrue(cur.moveToFirst());
    968         Assert.assertEquals("three", cur.getString(1));
    969         Assert.assertEquals("hello world", cur.getString(2));
    970         Assert.assertEquals(2345, cur.getLong(3));
    971         Assert.assertEquals(3456, cur.getLong(4));
    972         Assert.assertEquals("tricky", cur.getString(5));
    973         cur.close();
    974 
    975         cv = new ContentValues();
    976         cv.put("s", "three");
    977         cv.put("i", 6789);
    978         row = ih.insert(cv);
    979         Assert.assertEquals(-1, row);
    980         row = ih.replace(cv);
    981         cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null);
    982         Assert.assertTrue(cur.moveToFirst());
    983         Assert.assertEquals("three", cur.getString(1));
    984         Assert.assertEquals("hello world", cur.getString(2));
    985         Assert.assertEquals(6789, cur.getLong(3));
    986         cur.close();
    987 
    988         ih.close();
    989     }
    990 
    991     @MediumTest
    992     public void testDbCloseReleasingAllCachedSql() {
    993         mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, text1 TEXT, text2 TEXT, " +
    994                 "num1 INTEGER, num2 INTEGER, image BLOB);");
    995         final String statement = "DELETE FROM test WHERE _id=?;";
    996         SQLiteStatement statementDoNotClose = mDatabase.compileStatement(statement);
    997         assertTrue(statementDoNotClose.getUniqueId() > 0);
    998         int nStatement = statementDoNotClose.getUniqueId();
    999         assertTrue(statementDoNotClose.getUniqueId() == nStatement);
   1000         /* do not close statementDoNotClose object.
   1001          * That should leave it in SQLiteDatabase.mPrograms.
   1002          * mDatabase.close() in tearDown() should release it.
   1003          */
   1004     }
   1005 
   1006     @MediumTest
   1007     public void testSemicolonsInStatements() throws Exception {
   1008         mDatabase.execSQL("CREATE TABLE pragma_test (" +
   1009                 "i INTEGER DEFAULT 1234, " +
   1010                 "j INTEGER, " +
   1011                 "s TEXT DEFAULT 'hello', " +
   1012                 "t TEXT, " +
   1013                 "'select' TEXT DEFAULT \"hello\")");
   1014         try {
   1015             // ending the sql statement with  semicolons shouldn't be a problem.
   1016             Cursor cur = mDatabase.rawQuery("PRAGMA database_list;", null);
   1017             cur.close();
   1018             // two semicolons in the statement shouldn't be a problem.
   1019             cur = mDatabase.rawQuery("PRAGMA database_list;;", null);
   1020             cur.close();
   1021         } catch (Throwable t) {
   1022             fail("unexpected, of course");
   1023         }
   1024     }
   1025 
   1026     /**
   1027      * This test is available only when the platform has a locale with the language "ja".
   1028      * It finishes without failure when it is not available.
   1029      */
   1030     @MediumTest
   1031     public void testCollateLocalizedForJapanese() throws Exception {
   1032         final String testName = "DatabaseGeneralTest#testCollateLocalizedForJapanese()";
   1033         final Locale[] localeArray = Locale.getAvailableLocales();
   1034         final String japanese = Locale.JAPANESE.getLanguage();
   1035         final String english = Locale.ENGLISH.getLanguage();
   1036         Locale japaneseLocale = null;
   1037         Locale englishLocale = null;
   1038         for (Locale locale : localeArray) {
   1039             if (locale != null) {
   1040                 final String language = locale.getLanguage();
   1041                 if (language == null) {
   1042                     continue;
   1043                 } else if (language.equals(japanese)) {
   1044                     japaneseLocale = locale;
   1045                 } else if (language.equals(english)) {
   1046                     englishLocale = locale;
   1047                 }
   1048             }
   1049 
   1050             if (japaneseLocale != null && englishLocale != null) {
   1051                 break;
   1052             }
   1053         }
   1054 
   1055         if (japaneseLocale == null || englishLocale == null) {
   1056             Log.d(TAG, testName + "n is silently skipped since " +
   1057                     (englishLocale == null ?
   1058                             (japaneseLocale == null ?
   1059                                     "Both English and Japanese locales do not exist." :
   1060                                     "English locale does not exist.") :
   1061                             (japaneseLocale == null ?
   1062                                     "Japanese locale does not exist." :
   1063                                     "...why?")));
   1064             return;
   1065         }
   1066 
   1067         Locale originalLocale = Locale.getDefault();
   1068         try {
   1069 
   1070             final String dbName = "collate_localized_test";
   1071             mDatabase.execSQL("CREATE TABLE " + dbName + " (" +
   1072                     "_id INTEGER PRIMARY KEY, " +
   1073                     "s TEXT COLLATE LOCALIZED) ");
   1074             DatabaseUtils.InsertHelper ih =
   1075                 new DatabaseUtils.InsertHelper(mDatabase, dbName);
   1076             ContentValues cv = new ContentValues();
   1077 
   1078             cv = new ContentValues();  //
   1079             cv.put("s", "\uFF75\uFF77\uFF85\uFF9C");  // O-ki-na-wa in half-width Katakana
   1080             ih.insert(cv);
   1081 
   1082             cv = new ContentValues();  //
   1083             cv.put("s", "\u306B\u307B\u3093");  // Ni-ho-n in Hiragana
   1084             ih.insert(cv);
   1085 
   1086             cv = new ContentValues();  //
   1087             cv.put("s", "\u30A2\u30E1\u30EA\u30AB");  // A-me-ri-ca in hull-width Katakana
   1088             ih.insert(cv);
   1089 
   1090             // Assume setLocale() does REINDEX and an English locale does not consider
   1091             // Japanese-specific LOCALIZED order.
   1092             Locale.setDefault(englishLocale);
   1093             Locale.setDefault(japaneseLocale);
   1094 
   1095             Cursor cur = mDatabase.rawQuery(
   1096                     "SELECT * FROM " + dbName + " ORDER BY s", null);
   1097             assertTrue(cur.moveToFirst());
   1098             assertEquals("\u30A2\u30E1\u30EA\u30AB", cur.getString(1));
   1099             assertTrue(cur.moveToNext());
   1100             assertEquals("\uFF75\uFF77\uFF85\uFF9C", cur.getString(1));
   1101             assertTrue(cur.moveToNext());
   1102             assertEquals("\u306B\u307B\u3093", cur.getString(1));
   1103         } finally {
   1104             if (originalLocale != null) {
   1105                 try {
   1106                     Locale.setDefault(originalLocale);
   1107                 } catch (Exception e) {
   1108                 }
   1109             }
   1110         }
   1111     }
   1112 }
   1113