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