| /* |
| * Copyright (C) 2006 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.database; |
| |
| import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_COLUMNNAME_INDEX; |
| import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_DEFAULT_INDEX; |
| |
| import android.content.ContentValues; |
| import android.content.Context; |
| import android.database.sqlite.SQLiteDatabase; |
| import android.database.sqlite.SQLiteDebug; |
| import android.database.sqlite.SQLiteException; |
| import android.os.Parcel; |
| import android.test.AndroidTestCase; |
| import android.test.PerformanceTestCase; |
| import android.test.suitebuilder.annotation.LargeTest; |
| import android.test.suitebuilder.annotation.MediumTest; |
| import android.test.suitebuilder.annotation.SmallTest; |
| import android.util.Log; |
| import android.util.Pair; |
| |
| import junit.framework.Assert; |
| |
| import java.io.File; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Locale; |
| |
| /** |
| * Usage: bit FrameworksCoreTests:android.database.DatabaseGeneralTest |
| */ |
| public class DatabaseGeneralTest extends AndroidTestCase implements PerformanceTestCase { |
| private static final String TAG = "DatabaseGeneralTest"; |
| |
| private static final String sString1 = "this is a test"; |
| private static final String sString2 = "and yet another test"; |
| private static final String sString3 = "this string is a little longer, but still a test"; |
| private static final String PHONE_NUMBER = "16175551212"; |
| |
| private static final int CURRENT_DATABASE_VERSION = 42; |
| private SQLiteDatabase mDatabase; |
| private File mDatabaseFile; |
| |
| @Override |
| protected void setUp() throws Exception { |
| super.setUp(); |
| File dbDir = getContext().getDir(this.getClass().getName(), Context.MODE_PRIVATE); |
| mDatabaseFile = new File(dbDir, "database_test.db"); |
| if (mDatabaseFile.exists()) { |
| mDatabaseFile.delete(); |
| } |
| mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null); |
| assertNotNull(mDatabase); |
| mDatabase.setVersion(CURRENT_DATABASE_VERSION); |
| } |
| |
| @Override |
| protected void tearDown() throws Exception { |
| mDatabase.close(); |
| SQLiteDatabase.deleteDatabase(mDatabaseFile); |
| super.tearDown(); |
| } |
| |
| public boolean isPerformanceOnly() { |
| return false; |
| } |
| |
| // These test can only be run once. |
| public int startPerformance(Intermediates intermediates) { |
| return 1; |
| } |
| |
| private void populateDefaultTable() { |
| mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); |
| |
| mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString1 + "');"); |
| mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString2 + "');"); |
| mDatabase.execSQL("INSERT INTO test (data) VALUES ('" + sString3 + "');"); |
| } |
| |
| @MediumTest |
| public void testVersion() throws Exception { |
| assertEquals(CURRENT_DATABASE_VERSION, mDatabase.getVersion()); |
| mDatabase.setVersion(11); |
| assertEquals(11, mDatabase.getVersion()); |
| } |
| |
| @MediumTest |
| public void testUpdate() throws Exception { |
| populateDefaultTable(); |
| |
| ContentValues values = new ContentValues(1); |
| values.put("data", "this is an updated test"); |
| assertEquals(1, mDatabase.update("test", values, "_id=1", null)); |
| Cursor c = mDatabase.query("test", null, "_id=1", null, null, null, null); |
| assertNotNull(c); |
| assertEquals(1, c.getCount()); |
| c.moveToFirst(); |
| String value = c.getString(c.getColumnIndexOrThrow("data")); |
| assertEquals("this is an updated test", value); |
| } |
| |
| @MediumTest |
| public void testPhoneNumbersEqual() throws Exception { |
| mDatabase.execSQL("CREATE TABLE phones (num TEXT);"); |
| mDatabase.execSQL("INSERT INTO phones (num) VALUES ('911');"); |
| mDatabase.execSQL("INSERT INTO phones (num) VALUES ('5555');"); |
| mDatabase.execSQL("INSERT INTO phones (num) VALUES ('+" + PHONE_NUMBER + "');"); |
| |
| String number; |
| Cursor c; |
| |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '504-555-7683')", null, null, null, null); |
| assertTrue(c == null || c.getCount() == 0); |
| c.close(); |
| |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '911')", null, null, null, null); |
| assertNotNull(c); |
| assertEquals(1, c.getCount()); |
| c.moveToFirst(); |
| number = c.getString(c.getColumnIndexOrThrow("num")); |
| assertEquals("911", number); |
| c.close(); |
| |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '5555')", null, null, null, null); |
| assertNotNull(c); |
| assertEquals(1, c.getCount()); |
| c.moveToFirst(); |
| number = c.getString(c.getColumnIndexOrThrow("num")); |
| assertEquals("5555", number); |
| c.close(); |
| |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '180055555555')", null, null, null, null); |
| assertTrue(c == null || c.getCount() == 0); |
| c.close(); |
| |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '+" + PHONE_NUMBER + "')", null, null, null, null); |
| assertNotNull(c); |
| assertEquals(1, c.getCount()); |
| c.moveToFirst(); |
| number = c.getString(c.getColumnIndexOrThrow("num")); |
| assertEquals("+" + PHONE_NUMBER, number); |
| c.close(); |
| |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '+1 (617).555-1212')", null, null, null, null); |
| assertNotNull(c); |
| assertEquals(1, c.getCount()); |
| c.moveToFirst(); |
| number = c.getString(c.getColumnIndexOrThrow("num")); |
| assertEquals("+" + PHONE_NUMBER, number); |
| c.close(); |
| |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '" + PHONE_NUMBER + "')", null, null, null, null); |
| assertNotNull(c); |
| assertEquals(1, c.getCount()); |
| c.moveToFirst(); |
| number = c.getString(c.getColumnIndexOrThrow("num")); |
| assertEquals("+" + PHONE_NUMBER, number); |
| c.close(); |
| |
| /* |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '5551212')", null, null, null, null); |
| assertNotNull(c); |
| assertEquals(1, c.getCount()); |
| c.moveToFirst(); |
| number = c.getString(c.getColumnIndexOrThrow("num")); |
| assertEquals("+" + PHONE_NUMBER, number); |
| c.close(); |
| */ |
| |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '011" + PHONE_NUMBER + "')", null, null, null, null); |
| assertNotNull(c); |
| assertEquals(1, c.getCount()); |
| c.moveToFirst(); |
| number = c.getString(c.getColumnIndexOrThrow("num")); |
| assertEquals("+" + PHONE_NUMBER, number); |
| c.close(); |
| |
| c = mDatabase.query("phones", null, |
| "PHONE_NUMBERS_EQUAL(num, '00" + PHONE_NUMBER + "')", null, null, null, null); |
| assertNotNull(c); |
| assertEquals(1, c.getCount()); |
| c.moveToFirst(); |
| number = c.getString(c.getColumnIndexOrThrow("num")); |
| assertEquals("+" + PHONE_NUMBER, number); |
| c.close(); |
| } |
| |
| private void phoneNumberCompare(String phone1, String phone2, boolean equal, |
| boolean useStrictComparation) { |
| String[] temporalPhoneNumbers = new String[2]; |
| temporalPhoneNumbers[0] = phone1; |
| temporalPhoneNumbers[1] = phone2; |
| |
| Cursor cursor = mDatabase.rawQuery( |
| String.format( |
| "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?, %d) " + |
| "THEN 'equal' ELSE 'not equal' END", |
| (useStrictComparation ? 1 : 0)), |
| temporalPhoneNumbers); |
| try { |
| assertNotNull(cursor); |
| assertTrue(cursor.moveToFirst()); |
| if (equal) { |
| assertEquals(String.format("Unexpectedly, \"%s != %s\".", phone1, phone2), |
| "equal", cursor.getString(0)); |
| } else { |
| assertEquals(String.format("Unexpectedly, \"%s\" == \"%s\".", phone1, phone2), |
| "not equal", cursor.getString(0)); |
| } |
| } finally { |
| if (cursor != null) { |
| cursor.close(); |
| } |
| } |
| } |
| |
| private void assertPhoneNumberEqual(String phone1, String phone2) throws Exception { |
| assertPhoneNumberEqual(phone1, phone2, true); |
| assertPhoneNumberEqual(phone1, phone2, false); |
| } |
| |
| private void assertPhoneNumberEqual(String phone1, String phone2, boolean useStrict) |
| throws Exception { |
| phoneNumberCompare(phone1, phone2, true, useStrict); |
| } |
| |
| private void assertPhoneNumberNotEqual(String phone1, String phone2) throws Exception { |
| assertPhoneNumberNotEqual(phone1, phone2, true); |
| assertPhoneNumberNotEqual(phone1, phone2, false); |
| } |
| |
| private void assertPhoneNumberNotEqual(String phone1, String phone2, boolean useStrict) |
| throws Exception { |
| phoneNumberCompare(phone1, phone2, false, useStrict); |
| } |
| |
| /** |
| * Tests international matching issues for the PHONE_NUMBERS_EQUAL function. |
| * |
| * @throws Exception |
| */ |
| @SmallTest |
| public void testPhoneNumbersEqualInternationl() throws Exception { |
| assertPhoneNumberEqual("1", "1"); |
| assertPhoneNumberEqual("123123", "123123"); |
| assertPhoneNumberNotEqual("123123", "923123"); |
| assertPhoneNumberNotEqual("123123", "123129"); |
| assertPhoneNumberNotEqual("123123", "1231234"); |
| assertPhoneNumberNotEqual("123123", "0123123", false); |
| assertPhoneNumberNotEqual("123123", "0123123", true); |
| assertPhoneNumberEqual("650-253-0000", "6502530000"); |
| assertPhoneNumberEqual("650-253-0000", "650 253 0000"); |
| assertPhoneNumberEqual("650 253 0000", "6502530000"); |
| assertPhoneNumberEqual("+1 650-253-0000", "6502530000"); |
| assertPhoneNumberEqual("001 650-253-0000", "6502530000"); |
| assertPhoneNumberEqual("0111 650-253-0000", "6502530000"); |
| |
| // Russian trunk digit |
| assertPhoneNumberEqual("+79161234567", "89161234567"); |
| |
| // French trunk digit |
| assertPhoneNumberEqual("+33123456789", "0123456789"); |
| |
| // Trunk digit for city codes in the Netherlands |
| assertPhoneNumberEqual("+31771234567", "0771234567"); |
| |
| // Test broken caller ID seen on call from Thailand to the US |
| assertPhoneNumberEqual("+66811234567", "166811234567"); |
| |
| // Test the same in-country number with different country codes |
| assertPhoneNumberNotEqual("+33123456789", "+1123456789"); |
| |
| // Test one number with country code and the other without |
| assertPhoneNumberEqual("5125551212", "+15125551212"); |
| |
| // Test two NANP numbers that only differ in the area code |
| assertPhoneNumberNotEqual("5125551212", "6505551212"); |
| |
| // Japanese phone numbers |
| assertPhoneNumberEqual("090-1234-5678", "+819012345678"); |
| assertPhoneNumberEqual("090(1234)5678", "+819012345678"); |
| assertPhoneNumberEqual("090-1234-5678", "+81-90-1234-5678"); |
| |
| // Equador |
| assertPhoneNumberEqual("+593(800)123-1234", "8001231234"); |
| assertPhoneNumberEqual("+593-2-1234-123", "21234123"); |
| |
| // Two continuous 0 at the beginning of the phone string should not be |
| // treated as trunk prefix in the strict comparation. |
| assertPhoneNumberEqual("008001231234", "8001231234", false); |
| assertPhoneNumberNotEqual("008001231234", "8001231234", true); |
| |
| // Confirm that the bug found before does not re-appear in the strict compalation |
| assertPhoneNumberEqual("080-1234-5678", "+819012345678", false); |
| assertPhoneNumberNotEqual("080-1234-5678", "+819012345678", true); |
| } |
| |
| @MediumTest |
| public void testCopyString() throws Exception { |
| mDatabase.execSQL("CREATE TABLE guess (numi INTEGER, numf FLOAT, str TEXT);"); |
| mDatabase.execSQL( |
| "INSERT INTO guess (numi,numf,str) VALUES (0,0.0,'ZoomZoomZoomZoom');"); |
| mDatabase.execSQL("INSERT INTO guess (numi,numf,str) VALUES (2000000000,3.1415926535,'');"); |
| String chinese = "\u4eac\u4ec5 \u5c3d\u5f84\u60ca"; |
| String[] arr = new String[1]; |
| arr[0] = chinese; |
| mDatabase.execSQL("INSERT INTO guess (numi,numf,str) VALUES (-32768,-1.0,?)", arr); |
| |
| Cursor c; |
| |
| c = mDatabase.rawQuery("SELECT * FROM guess", null); |
| |
| c.moveToFirst(); |
| |
| CharArrayBuffer buf = new CharArrayBuffer(14); |
| |
| String compareTo = c.getString(c.getColumnIndexOrThrow("numi")); |
| int numiIdx = c.getColumnIndexOrThrow("numi"); |
| int numfIdx = c.getColumnIndexOrThrow("numf"); |
| int strIdx = c.getColumnIndexOrThrow("str"); |
| |
| c.copyStringToBuffer(numiIdx, buf); |
| assertEquals(1, buf.sizeCopied); |
| assertEquals(compareTo, new String(buf.data, 0, buf.sizeCopied)); |
| |
| c.copyStringToBuffer(strIdx, buf); |
| assertEquals("ZoomZoomZoomZoom", new String(buf.data, 0, buf.sizeCopied)); |
| |
| c.moveToNext(); |
| compareTo = c.getString(numfIdx); |
| |
| c.copyStringToBuffer(numfIdx, buf); |
| assertEquals(compareTo, new String(buf.data, 0, buf.sizeCopied)); |
| c.copyStringToBuffer(strIdx, buf); |
| assertEquals(0, buf.sizeCopied); |
| |
| c.moveToNext(); |
| c.copyStringToBuffer(numfIdx, buf); |
| assertEquals(-1.0, Double.valueOf( |
| new String(buf.data, 0, buf.sizeCopied)).doubleValue()); |
| |
| c.copyStringToBuffer(strIdx, buf); |
| compareTo = c.getString(strIdx); |
| assertEquals(chinese, compareTo); |
| |
| assertEquals(chinese, new String(buf.data, 0, buf.sizeCopied)); |
| c.close(); |
| } |
| |
| @MediumTest |
| public void testSchemaChange1() throws Exception { |
| SQLiteDatabase db1 = mDatabase; |
| Cursor cursor; |
| |
| db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); |
| |
| cursor = db1.query("db1", null, null, null, null, null, null); |
| assertNotNull("Cursor is null", cursor); |
| |
| db1.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);"); |
| |
| assertEquals(0, cursor.getCount()); |
| cursor.deactivate(); |
| } |
| |
| @MediumTest |
| public void testSchemaChange2() throws Exception { |
| mDatabase.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); |
| Cursor cursor = mDatabase.query("db1", null, null, null, null, null, null); |
| assertNotNull(cursor); |
| assertEquals(0, cursor.getCount()); |
| cursor.close(); |
| } |
| |
| @MediumTest |
| public void testSchemaChange3() throws Exception { |
| mDatabase.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); |
| mDatabase.execSQL("INSERT INTO db1 (data) VALUES ('test');"); |
| mDatabase.execSQL("ALTER TABLE db1 ADD COLUMN blah int;"); |
| Cursor c = null; |
| try { |
| c = mDatabase.rawQuery("select blah from db1", null); |
| } catch (SQLiteException e) { |
| fail("unexpected exception: " + e.getMessage()); |
| } finally { |
| if (c != null) { |
| c.close(); |
| } |
| } |
| } |
| |
| @MediumTest |
| public void testSelectionArgs() throws Exception { |
| mDatabase.execSQL("CREATE TABLE test (_id INTEGER PRIMARY KEY, data TEXT);"); |
| ContentValues values = new ContentValues(1); |
| values.put("data", "don't forget to handled 's"); |
| mDatabase.insert("test", "data", values); |
| values.clear(); |
| values.put("data", "no apostrophes here"); |
| mDatabase.insert("test", "data", values); |
| Cursor c = mDatabase.query( |
| "test", null, "data GLOB ?", new String[]{"*'*"}, null, null, null); |
| assertEquals(1, c.getCount()); |
| assertTrue(c.moveToFirst()); |
| assertEquals("don't forget to handled 's", c.getString(1)); |
| c.deactivate(); |
| |
| // make sure code should checking null string properly so that |
| // it won't crash |
| try { |
| mDatabase.query("test", new String[]{"_id"}, |
| "_id=?", new String[]{null}, null, null, null); |
| fail("expected exception not thrown"); |
| } catch (IllegalArgumentException e) { |
| // expected |
| } |
| } |
| |
| @MediumTest |
| public void testTokenize() throws Exception { |
| Cursor c; |
| mDatabase.execSQL("CREATE TABLE tokens (" + |
| "token TEXT COLLATE unicode," + |
| "source INTEGER," + |
| "token_index INTEGER," + |
| "tag TEXT" + |
| ");"); |
| mDatabase.execSQL("CREATE TABLE tokens_no_index (" + |
| "token TEXT COLLATE unicode," + |
| "source INTEGER" + |
| ");"); |
| |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE(NULL, NULL, NULL, NULL)", null)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE('tokens', NULL, NULL, NULL)", null)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE('tokens', 10, NULL, NULL)", null)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE('tokens', 10, 'some string', NULL)", null)); |
| |
| Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE('tokens', 11, 'some string ok', ' ', 1, 'foo')", null)); |
| Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE('tokens', 11, 'second field', ' ', 1, 'bar')", null)); |
| |
| Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE('tokens_no_index', 20, 'some string ok', ' ')", null)); |
| Assert.assertEquals(3, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE('tokens_no_index', 21, 'foo bar baz', ' ', 0)", null)); |
| |
| // test Chinese |
| String chinese = new String("\u4eac\u4ec5 \u5c3d\u5f84\u60ca"); |
| Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE('tokens', 12,'" + chinese + "', ' ', 1)", null)); |
| |
| String icustr = new String("Fr\u00e9d\u00e9ric Hj\u00f8nnev\u00e5g"); |
| |
| Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT _TOKENIZE('tokens', 13, '" + icustr + "', ' ', 1)", null)); |
| |
| Assert.assertEquals(9, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens;", null)); |
| |
| String key = DatabaseUtils.getHexCollationKey("Frederic Hjonneva"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| key = DatabaseUtils.getHexCollationKey("Hjonneva"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(13, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| |
| key = DatabaseUtils.getHexCollationKey("some string ok"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase, |
| "SELECT tag from tokens where token GLOB '" + key + "*'", null)); |
| key = DatabaseUtils.getHexCollationKey("string"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase, |
| "SELECT tag from tokens where token GLOB '" + key + "*'", null)); |
| key = DatabaseUtils.getHexCollationKey("ok"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals("foo", DatabaseUtils.stringForQuery(mDatabase, |
| "SELECT tag from tokens where token GLOB '" + key + "*'", null)); |
| |
| key = DatabaseUtils.getHexCollationKey("second field"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase, |
| "SELECT tag from tokens where token GLOB '" + key + "*'", null)); |
| key = DatabaseUtils.getHexCollationKey("field"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(11, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals("bar", DatabaseUtils.stringForQuery(mDatabase, |
| "SELECT tag from tokens where token GLOB '" + key + "*'", null)); |
| |
| key = DatabaseUtils.getHexCollationKey(chinese); |
| String[] a = new String[1]; |
| a[0] = key; |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token= ?", a)); |
| Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token= ?", a)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token= ?", a)); |
| a[0] += "*"; |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB ?", a)); |
| Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB ?", a)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB ?", a)); |
| |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token= '" + key + "'", null)); |
| Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token= '" + key + "'", null)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token= '" + key + "'", null)); |
| |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| |
| key = DatabaseUtils.getHexCollationKey("\u4eac\u4ec5"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| |
| key = DatabaseUtils.getHexCollationKey("\u5c3d\u5f84\u60ca"); |
| Log.d("DatabaseGeneralTest", "key = " + key); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(12, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT token_index from tokens where token GLOB '" + key + "*'", null)); |
| |
| Assert.assertEquals(0, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens where token GLOB 'ab*'", null)); |
| |
| key = DatabaseUtils.getHexCollationKey("some string ok"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(20, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null)); |
| |
| key = DatabaseUtils.getHexCollationKey("bar"); |
| Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT count(*) from tokens_no_index where token GLOB '" + key + "*'", null)); |
| Assert.assertEquals(21, DatabaseUtils.longForQuery(mDatabase, |
| "SELECT source from tokens_no_index where token GLOB '" + key + "*'", null)); |
| } |
| |
| @MediumTest |
| public void testTransactions() throws Exception { |
| mDatabase.execSQL("CREATE TABLE test (num INTEGER);"); |
| mDatabase.execSQL("INSERT INTO test (num) VALUES (0)"); |
| |
| // Make sure that things work outside an explicit transaction. |
| setNum(1); |
| checkNum(1); |
| |
| // Test a single-level transaction. |
| setNum(0); |
| mDatabase.beginTransaction(); |
| setNum(1); |
| mDatabase.setTransactionSuccessful(); |
| mDatabase.endTransaction(); |
| checkNum(1); |
| Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); |
| |
| // Test a rolled-back transaction. |
| setNum(0); |
| mDatabase.beginTransaction(); |
| setNum(1); |
| mDatabase.endTransaction(); |
| checkNum(0); |
| Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); |
| |
| // We should get an error if we end a non-existent transaction. |
| assertThrowsIllegalState(new Runnable() { public void run() { |
| mDatabase.endTransaction(); |
| }}); |
| |
| // We should get an error if a set a non-existent transaction as clean. |
| assertThrowsIllegalState(new Runnable() { public void run() { |
| mDatabase.setTransactionSuccessful(); |
| }}); |
| |
| mDatabase.beginTransaction(); |
| mDatabase.setTransactionSuccessful(); |
| // We should get an error if we mark a transaction as clean twice. |
| assertThrowsIllegalState(new Runnable() { public void run() { |
| mDatabase.setTransactionSuccessful(); |
| }}); |
| // We should get an error if we begin a transaction after marking the parent as clean. |
| assertThrowsIllegalState(new Runnable() { public void run() { |
| mDatabase.beginTransaction(); |
| }}); |
| mDatabase.endTransaction(); |
| Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); |
| |
| // Test a two-level transaction. |
| setNum(0); |
| mDatabase.beginTransaction(); |
| mDatabase.beginTransaction(); |
| setNum(1); |
| mDatabase.setTransactionSuccessful(); |
| mDatabase.endTransaction(); |
| mDatabase.setTransactionSuccessful(); |
| mDatabase.endTransaction(); |
| checkNum(1); |
| Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); |
| |
| // Test rolling back an inner transaction. |
| setNum(0); |
| mDatabase.beginTransaction(); |
| mDatabase.beginTransaction(); |
| setNum(1); |
| mDatabase.endTransaction(); |
| mDatabase.setTransactionSuccessful(); |
| mDatabase.endTransaction(); |
| checkNum(0); |
| Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); |
| |
| // Test rolling back an outer transaction. |
| setNum(0); |
| mDatabase.beginTransaction(); |
| mDatabase.beginTransaction(); |
| setNum(1); |
| mDatabase.setTransactionSuccessful(); |
| mDatabase.endTransaction(); |
| mDatabase.endTransaction(); |
| checkNum(0); |
| Assert.assertFalse(mDatabase.isDbLockedByCurrentThread()); |
| } |
| |
| private void setNum(int num) { |
| mDatabase.execSQL("UPDATE test SET num = " + num); |
| } |
| |
| private void checkNum(int num) { |
| Assert.assertEquals( |
| num, DatabaseUtils.longForQuery(mDatabase, "SELECT num FROM test", null)); |
| } |
| |
| private void assertThrowsIllegalState(Runnable r) { |
| boolean ok = false; |
| try { |
| r.run(); |
| } catch (IllegalStateException e) { |
| ok = true; |
| } |
| Assert.assertTrue(ok); |
| } |
| |
| // Disable these until we can explicitly mark them as stress tests |
| public void xxtestMem1() throws Exception { |
| populateDefaultTable(); |
| |
| for (int i = 0; i < 50000; i++) { |
| Cursor cursor = mDatabase.query("test", null, null, null, null, null, null); |
| cursor.moveToFirst(); |
| cursor.close(); |
| // Log.i("~~~~", "Finished round " + i); |
| } |
| } |
| |
| // Disable these until we can explicitly mark them as stress tests |
| public void xxtestMem2() throws Exception { |
| populateDefaultTable(); |
| |
| for (int i = 0; i < 50000; i++) { |
| Cursor cursor = mDatabase.query("test", null, null, null, null, null, null); |
| cursor.close(); |
| // Log.i("~~~~", "Finished round " + i); |
| } |
| } |
| |
| // Disable these until we can explicitly mark them as stress tests |
| public void xxtestMem3() throws Exception { |
| populateDefaultTable(); |
| |
| for (int i = 0; i < 50000; i++) { |
| Cursor cursor = mDatabase.query("test", null, null, null, null, null, null); |
| cursor.deactivate(); |
| // Log.i("~~~~", "Finished round " + i); |
| } |
| } |
| |
| @MediumTest |
| public void testContentValues() throws Exception { |
| ContentValues values = new ContentValues(); |
| values.put("string", "value"); |
| assertEquals("value", values.getAsString("string")); |
| byte[] bytes = new byte[42]; |
| Arrays.fill(bytes, (byte) 0x28); |
| values.put("byteArray", bytes); |
| assertTrue(Arrays.equals(bytes, values.getAsByteArray("byteArray"))); |
| |
| // Write the ContentValues to a Parcel and then read them out |
| Parcel p = Parcel.obtain(); |
| values.writeToParcel(p, 0); |
| p.setDataPosition(0); |
| values = ContentValues.CREATOR.createFromParcel(p); |
| |
| // Read the values out again and make sure they're the same |
| assertTrue(Arrays.equals(bytes, values.getAsByteArray("byteArray"))); |
| assertEquals("value", values.get("string")); |
| } |
| |
| @MediumTest |
| public void testTableInfoPragma() throws Exception { |
| mDatabase.execSQL("CREATE TABLE pragma_test (" + |
| "i INTEGER DEFAULT 1234, " + |
| "j INTEGER, " + |
| "s TEXT DEFAULT 'hello', " + |
| "t TEXT, " + |
| "'select' TEXT DEFAULT \"hello\")"); |
| try { |
| Cursor cur = mDatabase.rawQuery("PRAGMA table_info(pragma_test)", null); |
| Assert.assertEquals(5, cur.getCount()); |
| |
| Assert.assertTrue(cur.moveToNext()); |
| Assert.assertEquals("i", |
| cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); |
| Assert.assertEquals("1234", |
| cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); |
| |
| Assert.assertTrue(cur.moveToNext()); |
| Assert.assertEquals("j", |
| cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); |
| Assert.assertNull(cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); |
| |
| Assert.assertTrue(cur.moveToNext()); |
| Assert.assertEquals("s", |
| cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); |
| Assert.assertEquals("'hello'", |
| cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); |
| |
| Assert.assertTrue(cur.moveToNext()); |
| Assert.assertEquals("t", |
| cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); |
| Assert.assertNull(cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); |
| |
| Assert.assertTrue(cur.moveToNext()); |
| Assert.assertEquals("select", |
| cur.getString(TABLE_INFO_PRAGMA_COLUMNNAME_INDEX)); |
| Assert.assertEquals("\"hello\"", |
| cur.getString(TABLE_INFO_PRAGMA_DEFAULT_INDEX)); |
| |
| cur.close(); |
| } catch (Throwable t) { |
| throw new RuntimeException( |
| "If you see this test fail, it's likely that something about " + |
| "sqlite's PRAGMA table_info(...) command has changed.", t); |
| } |
| } |
| |
| @MediumTest |
| public void testInsertHelper() throws Exception { |
| Cursor cur; |
| ContentValues cv; |
| long row; |
| |
| mDatabase.execSQL("CREATE TABLE insert_test (" + |
| "_id INTEGER PRIMARY KEY, " + |
| "s TEXT NOT NULL UNIQUE, " + |
| "t TEXT NOT NULL DEFAULT 'hello world', " + |
| "i INTEGER, " + |
| "j INTEGER NOT NULL DEFAULT 1234, " + |
| "'select' TEXT)"); |
| |
| DatabaseUtils.InsertHelper ih = |
| new DatabaseUtils.InsertHelper(mDatabase, "insert_test"); |
| |
| cv = new ContentValues(); |
| cv.put("s", "one"); |
| row = ih.insert(cv); |
| cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); |
| Assert.assertTrue(cur.moveToFirst()); |
| Assert.assertEquals("one", cur.getString(1)); |
| Assert.assertEquals("hello world", cur.getString(2)); |
| Assert.assertNull(cur.getString(3)); |
| Assert.assertEquals(1234, cur.getLong(4)); |
| Assert.assertNull(cur.getString(5)); |
| cur.close(); |
| |
| cv = new ContentValues(); |
| cv.put("s", "two"); |
| cv.put("t", "goodbye world"); |
| row = ih.insert(cv); |
| cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); |
| Assert.assertTrue(cur.moveToFirst()); |
| Assert.assertEquals("two", cur.getString(1)); |
| Assert.assertEquals("goodbye world", cur.getString(2)); |
| Assert.assertNull(cur.getString(3)); |
| Assert.assertEquals(1234, cur.getLong(4)); |
| Assert.assertNull(cur.getString(5)); |
| cur.close(); |
| |
| cv = new ContentValues(); |
| cv.put("t", "goodbye world"); |
| row = ih.insert(cv); |
| Assert.assertEquals(-1, row); |
| |
| cv = new ContentValues(); |
| cv.put("s", "three"); |
| cv.put("i", 2345); |
| cv.put("j", 3456); |
| cv.put("select", "tricky"); |
| row = ih.insert(cv); |
| cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); |
| Assert.assertTrue(cur.moveToFirst()); |
| Assert.assertEquals("three", cur.getString(1)); |
| Assert.assertEquals("hello world", cur.getString(2)); |
| Assert.assertEquals(2345, cur.getLong(3)); |
| Assert.assertEquals(3456, cur.getLong(4)); |
| Assert.assertEquals("tricky", cur.getString(5)); |
| cur.close(); |
| |
| cv = new ContentValues(); |
| cv.put("s", "three"); |
| cv.put("i", 6789); |
| row = ih.insert(cv); |
| Assert.assertEquals(-1, row); |
| row = ih.replace(cv); |
| cur = mDatabase.rawQuery("SELECT * FROM insert_test WHERE _id == " + row, null); |
| Assert.assertTrue(cur.moveToFirst()); |
| Assert.assertEquals("three", cur.getString(1)); |
| Assert.assertEquals("hello world", cur.getString(2)); |
| Assert.assertEquals(6789, cur.getLong(3)); |
| cur.close(); |
| |
| ih.close(); |
| } |
| |
| @MediumTest |
| public void testSemicolonsInStatements() throws Exception { |
| mDatabase.execSQL("CREATE TABLE pragma_test (" + |
| "i INTEGER DEFAULT 1234, " + |
| "j INTEGER, " + |
| "s TEXT DEFAULT 'hello', " + |
| "t TEXT, " + |
| "'select' TEXT DEFAULT \"hello\")"); |
| try { |
| // ending the sql statement with semicolons shouldn't be a problem. |
| Cursor cur = mDatabase.rawQuery("PRAGMA database_list;", null); |
| cur.close(); |
| // two semicolons in the statement shouldn't be a problem. |
| cur = mDatabase.rawQuery("PRAGMA database_list;;", null); |
| cur.close(); |
| } catch (Throwable t) { |
| fail("unexpected, of course"); |
| } |
| } |
| |
| @MediumTest |
| public void testUnionsWithBindArgs() { |
| /* make sure unions with bindargs work http://b/issue?id=1061291 */ |
| mDatabase.execSQL("CREATE TABLE A (i int);"); |
| mDatabase.execSQL("create table B (k int);"); |
| mDatabase.execSQL("create table C (n int);"); |
| mDatabase.execSQL("insert into A values(1);"); |
| mDatabase.execSQL("insert into A values(2);"); |
| mDatabase.execSQL("insert into A values(3);"); |
| mDatabase.execSQL("insert into B values(201);"); |
| mDatabase.execSQL("insert into B values(202);"); |
| mDatabase.execSQL("insert into B values(203);"); |
| mDatabase.execSQL("insert into C values(901);"); |
| mDatabase.execSQL("insert into C values(902);"); |
| String s = "select i from A where i > 2 " + |
| "UNION select k from B where k > 201 " + |
| "UNION select n from C where n !=900;"; |
| Cursor c = mDatabase.rawQuery(s, null); |
| int n = c.getCount(); |
| c.close(); |
| String s1 = "select i from A where i > ? " + |
| "UNION select k from B where k > ? " + |
| "UNION select n from C where n != ?;"; |
| Cursor c1 = mDatabase.rawQuery(s1, new String[]{"2", "201", "900"}); |
| assertEquals(n, c1.getCount()); |
| c1.close(); |
| } |
| |
| /** |
| * This test is available only when the platform has a locale with the language "ja". |
| * It finishes without failure when it is not available. |
| */ |
| @MediumTest |
| public void testCollateLocalizedForJapanese() throws Exception { |
| final String testName = "DatabaseGeneralTest#testCollateLocalizedForJapanese()"; |
| final Locale[] localeArray = Locale.getAvailableLocales(); |
| final String japanese = Locale.JAPANESE.getLanguage(); |
| final String english = Locale.ENGLISH.getLanguage(); |
| Locale japaneseLocale = null; |
| Locale englishLocale = null; |
| for (Locale locale : localeArray) { |
| if (locale != null) { |
| final String language = locale.getLanguage(); |
| if (language == null) { |
| continue; |
| } else if (language.equals(japanese)) { |
| japaneseLocale = locale; |
| } else if (language.equals(english)) { |
| englishLocale = locale; |
| } |
| } |
| |
| if (japaneseLocale != null && englishLocale != null) { |
| break; |
| } |
| } |
| |
| if (japaneseLocale == null || englishLocale == null) { |
| Log.d(TAG, testName + "n is silently skipped since " + |
| (englishLocale == null ? |
| (japaneseLocale == null ? |
| "Both English and Japanese locales do not exist." : |
| "English locale does not exist.") : |
| (japaneseLocale == null ? |
| "Japanese locale does not exist." : |
| "...why?"))); |
| return; |
| } |
| |
| Locale originalLocale = Locale.getDefault(); |
| try { |
| |
| final String dbName = "collate_localized_test"; |
| mDatabase.execSQL("CREATE TABLE " + dbName + " (" + |
| "_id INTEGER PRIMARY KEY, " + |
| "s TEXT COLLATE LOCALIZED) "); |
| DatabaseUtils.InsertHelper ih = |
| new DatabaseUtils.InsertHelper(mDatabase, dbName); |
| ContentValues cv = new ContentValues(); |
| |
| cv = new ContentValues(); // |
| cv.put("s", "\uFF75\uFF77\uFF85\uFF9C"); // O-ki-na-wa in half-width Katakana |
| ih.insert(cv); |
| |
| cv = new ContentValues(); // |
| cv.put("s", "\u306B\u307B\u3093"); // Ni-ho-n in Hiragana |
| ih.insert(cv); |
| |
| cv = new ContentValues(); // |
| cv.put("s", "\u30A2\u30E1\u30EA\u30AB"); // A-me-ri-ca in hull-width Katakana |
| ih.insert(cv); |
| |
| // Assume setLocale() does REINDEX and an English locale does not consider |
| // Japanese-specific LOCALIZED order. |
| Locale.setDefault(englishLocale); |
| Locale.setDefault(japaneseLocale); |
| |
| Cursor cur = mDatabase.rawQuery( |
| "SELECT * FROM " + dbName + " ORDER BY s", null); |
| assertTrue(cur.moveToFirst()); |
| assertEquals("\u30A2\u30E1\u30EA\u30AB", cur.getString(1)); |
| assertTrue(cur.moveToNext()); |
| assertEquals("\uFF75\uFF77\uFF85\uFF9C", cur.getString(1)); |
| assertTrue(cur.moveToNext()); |
| assertEquals("\u306B\u307B\u3093", cur.getString(1)); |
| } finally { |
| if (originalLocale != null) { |
| try { |
| Locale.setDefault(originalLocale); |
| } catch (Exception e) { |
| } |
| } |
| } |
| } |
| |
| @SmallTest |
| public void testSetMaxCahesize() { |
| mDatabase.execSQL("CREATE TABLE test (i int, j int);"); |
| mDatabase.execSQL("insert into test values(1,1);"); |
| // set cache size |
| int N = SQLiteDatabase.MAX_SQL_CACHE_SIZE; |
| mDatabase.setMaxSqlCacheSize(N); |
| |
| // try reduce cachesize |
| try { |
| mDatabase.setMaxSqlCacheSize(1); |
| } catch (IllegalStateException e) { |
| assertTrue(e.getMessage().contains("cannot set cacheSize to a value less than")); |
| } |
| } |
| |
| @SmallTest |
| public void testOpenDatabaseLookasideConfig() { |
| // First check that lookaside is active |
| verifyLookasideStats(false); |
| // Reopen test db with lookaside disabled |
| mDatabase.close(); |
| SQLiteDatabase.OpenParams params = new SQLiteDatabase.OpenParams.Builder() |
| .setLookasideConfig(0, 0).build(); |
| mDatabase = SQLiteDatabase.openDatabase(mDatabaseFile.getPath(), params); |
| verifyLookasideStats(true); |
| } |
| |
| @SmallTest |
| public void testOpenParamsSetLookasideConfigValidation() { |
| try { |
| SQLiteDatabase.OpenParams params = new SQLiteDatabase.OpenParams.Builder() |
| .setLookasideConfig(-1, 0).build(); |
| fail("Negative slot size should be rejected"); |
| } catch (IllegalArgumentException expected) { |
| } |
| try { |
| SQLiteDatabase.OpenParams params = new SQLiteDatabase.OpenParams.Builder() |
| .setLookasideConfig(0, -10).build(); |
| fail("Negative slot count should be rejected"); |
| } catch (IllegalArgumentException expected) { |
| } |
| } |
| |
| void verifyLookasideStats(boolean expectDisabled) { |
| boolean dbStatFound = false; |
| SQLiteDebug.PagerStats info = SQLiteDebug.getDatabaseInfo(); |
| for (SQLiteDebug.DbStats dbStat : info.dbStats) { |
| if (dbStat.dbName.endsWith(mDatabaseFile.getName())) { |
| dbStatFound = true; |
| Log.i(TAG, "Lookaside for " + dbStat.dbName + " " + dbStat.lookaside); |
| if (expectDisabled) { |
| assertTrue("lookaside slots count should be zero", dbStat.lookaside == 0); |
| } else { |
| assertTrue("lookaside slots count should be greater than zero", |
| dbStat.lookaside > 0); |
| } |
| } |
| } |
| assertTrue("No dbstat found for " + mDatabaseFile.getName(), dbStatFound); |
| } |
| |
| @LargeTest |
| public void testDefaultDatabaseErrorHandler() { |
| DefaultDatabaseErrorHandler errorHandler = new DefaultDatabaseErrorHandler(); |
| |
| // close the database. and call corruption handler. |
| // it should delete the database file. |
| File dbfile = new File(mDatabase.getPath()); |
| mDatabase.close(); |
| assertFalse(mDatabase.isOpen()); |
| assertTrue(dbfile.exists()); |
| try { |
| errorHandler.onCorruption(mDatabase); |
| assertFalse(dbfile.exists()); |
| } catch (Exception e) { |
| fail("unexpected"); |
| } |
| |
| // create an in-memory database. and corruption handler shouldn't try to delete it |
| SQLiteDatabase memoryDb = SQLiteDatabase.openOrCreateDatabase(":memory:", null); |
| assertNotNull(memoryDb); |
| memoryDb.close(); |
| assertFalse(memoryDb.isOpen()); |
| try { |
| errorHandler.onCorruption(memoryDb); |
| } catch (Exception e) { |
| fail("unexpected"); |
| } |
| |
| // create a database, keep it open, call corruption handler. database file should be deleted |
| SQLiteDatabase dbObj = SQLiteDatabase.openOrCreateDatabase(mDatabase.getPath(), null); |
| assertTrue(dbfile.exists()); |
| assertNotNull(dbObj); |
| assertTrue(dbObj.isOpen()); |
| try { |
| errorHandler.onCorruption(dbObj); |
| assertFalse(dbfile.exists()); |
| } catch (Exception e) { |
| fail("unexpected"); |
| } |
| |
| // create a database, attach 2 more databases to it |
| // attached database # 1: ":memory:" |
| // attached database # 2: mDatabase.getPath() + "1"; |
| // call corruption handler. database files including the one for attached database # 2 |
| // should be deleted |
| String attachedDb1File = mDatabase.getPath() + "1"; |
| dbObj = SQLiteDatabase.openOrCreateDatabase(mDatabase.getPath(), null); |
| dbObj.execSQL("ATTACH DATABASE ':memory:' as memoryDb"); |
| dbObj.execSQL("ATTACH DATABASE '" + attachedDb1File + "' as attachedDb1"); |
| assertTrue(dbfile.exists()); |
| assertTrue(new File(attachedDb1File).exists()); |
| assertNotNull(dbObj); |
| assertTrue(dbObj.isOpen()); |
| List<Pair<String, String>> attachedDbs = dbObj.getAttachedDbs(); |
| try { |
| errorHandler.onCorruption(dbObj); |
| assertFalse(dbfile.exists()); |
| assertFalse(new File(attachedDb1File).exists()); |
| } catch (Exception e) { |
| fail("unexpected"); |
| } |
| |
| // same as above, except this is a bit of stress testing. attach 5 database files |
| // and make sure they are all removed. |
| int N = 5; |
| ArrayList<String> attachedDbFiles = new ArrayList<String>(N); |
| for (int i = 0; i < N; i++) { |
| attachedDbFiles.add(mDatabase.getPath() + i); |
| } |
| dbObj = SQLiteDatabase.openOrCreateDatabase(mDatabase.getPath(), null); |
| dbObj.execSQL("ATTACH DATABASE ':memory:' as memoryDb"); |
| for (int i = 0; i < N; i++) { |
| dbObj.execSQL("ATTACH DATABASE '" + attachedDbFiles.get(i) + "' as attachedDb" + i); |
| } |
| assertTrue(dbfile.exists()); |
| for (int i = 0; i < N; i++) { |
| assertTrue(new File(attachedDbFiles.get(i)).exists()); |
| } |
| assertNotNull(dbObj); |
| assertTrue(dbObj.isOpen()); |
| attachedDbs = dbObj.getAttachedDbs(); |
| try { |
| errorHandler.onCorruption(dbObj); |
| assertFalse(dbfile.exists()); |
| for (int i = 0; i < N; i++) { |
| assertFalse(new File(attachedDbFiles.get(i)).exists()); |
| } |
| } catch (Exception e) { |
| fail("unexpected"); |
| } |
| } |
| } |