diff options
Diffstat (limited to 'tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java')
-rw-r--r-- | tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java | 871 |
1 files changed, 871 insertions, 0 deletions
diff --git a/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java new file mode 100644 index 0000000..b004c93 --- /dev/null +++ b/tests/AndroidTests/src/com/android/unit_tests/DatabaseGeneralTest.java @@ -0,0 +1,871 @@ +/* + * 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 com.android.unit_tests; + +import android.content.ContentValues; +import android.database.ContentObserver; +import android.database.Cursor; +import android.database.DatabaseUtils; +import android.database.CharArrayBuffer; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteStatement; +import android.os.Handler; +import android.os.Parcel; +import android.test.PerformanceTestCase; +import android.test.suitebuilder.annotation.MediumTest; +import android.test.suitebuilder.annotation.SmallTest; +import android.util.Log; + +import java.io.File; +import java.io.UnsupportedEncodingException; +import java.text.Collator; +import java.util.Arrays; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_COLUMNNAME_INDEX; +import static android.database.DatabaseUtils.InsertHelper.TABLE_INFO_PRAGMA_DEFAULT_INDEX; + +public class DatabaseGeneralTest extends TestCase implements PerformanceTestCase { + + 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(); + mDatabaseFile = new File("/sqlite_stmt_journals", "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(); + mDatabaseFile.delete(); + 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, '+1 (617).555-1212p1234')", 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(); + } + + /** + * Tests international matching issues for the PHONE_NUMBERS_EQUAL function. + * + * @throws Exception + */ + public void testPhoneNumbersEqualInternationl() throws Exception { + Cursor c; + String[] phoneNumbers = new String[2]; + + // Russian trunk digit + phoneNumbers[0] = "+79161234567"; // globablly dialable number + phoneNumbers[1] = "89161234567"; // in-country dialable number + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + // French trunk digit + phoneNumbers[0] = "+33123456789"; // globablly dialable number + phoneNumbers[1] = "0123456789"; // in-country dialable number + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + + // Trunk digit for city codes in the Netherlands + phoneNumbers[0] = "+31771234567"; // globablly dialable number + phoneNumbers[1] = "0771234567"; // in-country dialable number + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + // Test broken caller ID seen on call from Thailand to the US + phoneNumbers[0] = "+66811234567"; // in address book + phoneNumbers[1] = "166811234567"; // came in from the network + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + // Test the same in-country number with different country codes + phoneNumbers[0] = "+33123456789"; + phoneNumbers[1] = "+1123456789"; + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("not equal", c.getString(0)); + c.close(); + + // Test one number with country code and the other without + phoneNumbers[0] = "5125551212"; + phoneNumbers[1] = "+15125551212"; + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("equal", c.getString(0)); + c.close(); + + // Test two NANP numbers that only differ in the area code + phoneNumbers[0] = "5125551212"; + phoneNumbers[1] = "6505551212"; + c = mDatabase.rawQuery( + "SELECT CASE WHEN PHONE_NUMBERS_EQUAL(?, ?) THEN 'equal' ELSE 'not equal' END", + phoneNumbers); + assertTrue(c.moveToFirst()); + assertEquals("not equal", c.getString(0)); + c.close(); + } + + @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 { + SQLiteDatabase db1 = mDatabase; + SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile, null); + 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); + assertEquals(0, cursor.getCount()); + cursor.deactivate(); + // this cause exception because we're still using sqlite_prepate16 and not + // sqlite_prepare16_v2. The v2 variant added the ability to check the + // schema version and handle the case when the schema has changed + // Marco Nelissen claim it was 2x slower to compile SQL statements so + // I reverted back to the v1 variant. + /* db2.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);"); + + cursor = db1.query("db1", null, null, null, null, null, null); + assertNotNull("Cursor is null", cursor); + assertEquals(0, cursor.count()); + cursor.deactivate(); + */ + } + + @MediumTest + public void testSchemaChange3() throws Exception { + SQLiteDatabase db1 = mDatabase; + SQLiteDatabase db2 = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile, null); + Cursor cursor; + + + db1.execSQL("CREATE TABLE db1 (_id INTEGER PRIMARY KEY, data TEXT);"); + db1.execSQL("INSERT INTO db1 (data) VALUES ('test');"); + + cursor = db1.query("db1", null, null, null, null, null, null); + // this cause exception because we're still using sqlite_prepate16 and not + // sqlite_prepare16_v2. The v2 variant added the ability to check the + // schema version and handle the case when the schema has changed + // Marco Nelissen claim it was 2x slower to compile SQL statements so + // I reverted back to the v1 variant. + /* db2.execSQL("CREATE TABLE db2 (_id INTEGER PRIMARY KEY, data TEXT);"); + + assertNotNull("Cursor is null", cursor); + assertEquals(1, cursor.count()); + assertTrue(cursor.first()); + assertEquals("test", cursor.getString(cursor.getColumnIndexOrThrow("data"))); + cursor.deactivate(); + */ + } + + private class ChangeObserver extends ContentObserver { + private int mCursorNotificationCount = 0; + private int mNotificationCount = 0; + + public int getCursorNotificationCount() { + return mCursorNotificationCount; + } + + public int getNotificationCount() { + return mNotificationCount; + } + + public ChangeObserver(boolean cursor) { + super(new Handler()); + mCursor = cursor; + } + + @Override + public boolean deliverSelfNotifications() { + return true; + } + + @Override + public void onChange(boolean selfChange) { + if (mCursor) { + mCursorNotificationCount++; + } else { + mNotificationCount++; + } + } + + boolean mCursor; + } + + @MediumTest + public void testNotificationTest1() throws Exception { + /* + Cursor c = mContentResolver.query(Notes.CONTENT_URI, + new String[] {Notes._ID, Notes.NOTE}, + null, null); + c.registerContentObserver(new MyContentObserver(true)); + int count = c.count(); + + MyContentObserver observer = new MyContentObserver(false); + mContentResolver.registerContentObserver(Notes.CONTENT_URI, true, observer); + + Uri uri; + + HashMap<String, String> values = new HashMap<String, String>(); + values.put(Notes.NOTE, "test note1"); + uri = mContentResolver.insert(Notes.CONTENT_URI, values); + assertEquals(1, mCursorNotificationCount); + assertEquals(1, mNotificationCount); + + c.requery(); + assertEquals(count + 1, c.count()); + c.first(); + assertEquals("test note1", c.getString(c.getColumnIndex(Notes.NOTE))); + c.updateString(c.getColumnIndex(Notes.NOTE), "test note2"); + c.commitUpdates(); + + assertEquals(2, mCursorNotificationCount); + assertEquals(2, mNotificationCount); + + mContentResolver.delete(uri, null); + + assertEquals(3, mCursorNotificationCount); + assertEquals(3, mNotificationCount); + + mContentResolver.unregisterContentObserver(observer); + */ + } + + @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 " + + ");"); + String[] cols = new String[]{"token", "source"}; + + 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', 1, 'some string ok', ' ')", null)); + + // test Chinese + String chinese = new String("\u4eac\u4ec5 \u5c3d\u5f84\u60ca"); + Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens', 1,'" + chinese + "', ' ')", null)); + + String icustr = new String("Fr\u00e9d\u00e9ric Hj\u00f8nnev\u00e5g"); + + Assert.assertEquals(2, DatabaseUtils.longForQuery(mDatabase, + "SELECT _TOKENIZE('tokens', 1, '" + icustr + "', ' ')", null)); + + Assert.assertEquals(7, 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)); + key = DatabaseUtils.getHexCollationKey("Hjonneva"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) 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)); + key = DatabaseUtils.getHexCollationKey("string"); + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) 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)); + + 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)); + a[0] += "*"; + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB ?", a)); + + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token= '" + key + "'", null)); + + Assert.assertEquals(1, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) 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(0, DatabaseUtils.longForQuery(mDatabase, + "SELECT count(*) from tokens where token GLOB 'ab*'", 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)); + + 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)); + + 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)); + + 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)); + + ih.close(); + } + +} |