package org.robolectric.shadows; import android.content.ContentValues; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.TestRunners; import static org.assertj.core.api.Assertions.assertThat; @RunWith(TestRunners.MultiApiSelfTest.class) public class SQLiteOpenHelperTest { private TestOpenHelper helper; @Before public void setUp() throws Exception { helper = new TestOpenHelper(RuntimeEnvironment.application, "path", null, 1); } @After public void tearDown() { helper.close(); } @Test public void testConstructorWithNullPathShouldCreateInMemoryDatabase() throws Exception { TestOpenHelper helper = new TestOpenHelper(null, null, null, 1); SQLiteDatabase database = helper.getReadableDatabase(); assertDatabaseOpened(database, helper); assertInitialDB(database, helper); } @Test public void testInitialGetReadableDatabase() throws Exception { SQLiteDatabase database = helper.getReadableDatabase(); assertInitialDB(database, helper); } @Test public void testSubsequentGetReadableDatabase() throws Exception { helper.getReadableDatabase(); helper.close(); SQLiteDatabase database = helper.getReadableDatabase(); assertSubsequentDB(database, helper); } @Test public void testSameDBInstanceSubsequentGetReadableDatabase() throws Exception { SQLiteDatabase db1 = helper.getReadableDatabase(); SQLiteDatabase db2 = helper.getReadableDatabase(); assertThat(db1).isSameAs(db2); } @Test public void testInitialGetWritableDatabase() throws Exception { SQLiteDatabase database = helper.getWritableDatabase(); assertInitialDB(database, helper); } @Test public void testSubsequentGetWritableDatabase() throws Exception { helper.getWritableDatabase(); helper.close(); assertSubsequentDB(helper.getWritableDatabase(), helper); } @Test public void testSameDBInstanceSubsequentGetWritableDatabase() throws Exception { SQLiteDatabase db1 = helper.getWritableDatabase(); SQLiteDatabase db2 = helper.getWritableDatabase(); assertThat(db1).isSameAs(db2); } @Test public void testClose() throws Exception { SQLiteDatabase database = helper.getWritableDatabase(); assertThat(database.isOpen()).isTrue(); helper.close(); assertThat(database.isOpen()).isFalse(); } @Test public void testGetPath() throws Exception { final String path1 = "path1", path2 = "path2"; TestOpenHelper helper1 = new TestOpenHelper(RuntimeEnvironment.application, path1, null, 1); String expectedPath1 = RuntimeEnvironment.application.getDatabasePath(path1).getAbsolutePath(); assertThat(helper1.getReadableDatabase().getPath()).isEqualTo(expectedPath1); TestOpenHelper helper2 = new TestOpenHelper(RuntimeEnvironment.application, path2, null, 1); String expectedPath2 = RuntimeEnvironment.application.getDatabasePath(path2).getAbsolutePath(); assertThat(helper2.getReadableDatabase().getPath()).isEqualTo(expectedPath2); } @Test public void testCloseMultipleDbs() throws Exception { TestOpenHelper helper2 = new TestOpenHelper(RuntimeEnvironment.application, "path2", null, 1); SQLiteDatabase database1 = helper.getWritableDatabase(); SQLiteDatabase database2 = helper2.getWritableDatabase(); assertThat(database1.isOpen()).isTrue(); assertThat(database2.isOpen()).isTrue(); helper.close(); assertThat(database1.isOpen()).isFalse(); assertThat(database2.isOpen()).isTrue(); helper2.close(); assertThat(database2.isOpen()).isFalse(); } @Test public void testOpenMultipleDbsOnCreate() throws Exception { TestOpenHelper helper2 = new TestOpenHelper(RuntimeEnvironment.application, "path2", null, 1); assertThat(helper.onCreateCalled).isFalse(); assertThat(helper2.onCreateCalled).isFalse(); helper.getWritableDatabase(); assertThat(helper.onCreateCalled).isTrue(); assertThat(helper2.onCreateCalled).isFalse(); helper2.getWritableDatabase(); assertThat(helper.onCreateCalled).isTrue(); assertThat(helper2.onCreateCalled).isTrue(); helper.close(); helper2.close(); } private void setupTable(SQLiteDatabase db, String table) { db.execSQL("CREATE TABLE " + table + " (" + "id INTEGER PRIMARY KEY AUTOINCREMENT, " + "testVal INTEGER DEFAULT 0" + ");"); } private void insertData(SQLiteDatabase db, String table, int[] values) { for (int i : values) { ContentValues cv = new ContentValues(); cv.put("testVal", i); db.insert(table, null, cv); } } private void verifyData(SQLiteDatabase db, String table, int expectedVals) { assertThat(db.query(table, null, null, null, null, null, null).getCount()).isEqualTo(expectedVals); } @Test public void testMultipleDbsPreserveData() throws Exception { final String TABLE_NAME1 = "fart", TABLE_NAME2 = "fart2"; SQLiteDatabase db1 = helper.getWritableDatabase(); setupTable(db1, TABLE_NAME1); insertData(db1, TABLE_NAME1, new int[]{1, 2}); TestOpenHelper helper2 = new TestOpenHelper(RuntimeEnvironment.application, "path2", null, 1); SQLiteDatabase db2 = helper2.getWritableDatabase(); setupTable(db2, TABLE_NAME2); insertData(db2, TABLE_NAME2, new int[]{4, 5, 6}); verifyData(db1, TABLE_NAME1, 2); verifyData(db2, TABLE_NAME2, 3); } @Test public void testCloseOneDbKeepsDataForOther() throws Exception { final String TABLE_NAME1 = "fart", TABLE_NAME2 = "fart2"; TestOpenHelper helper2 = new TestOpenHelper(RuntimeEnvironment.application, "path2", null, 1); SQLiteDatabase db1 = helper.getWritableDatabase(); SQLiteDatabase db2 = helper2.getWritableDatabase(); setupTable(db1, TABLE_NAME1); setupTable(db2, TABLE_NAME2); insertData(db1, TABLE_NAME1, new int[]{1, 2}); insertData(db2, TABLE_NAME2, new int[]{4, 5, 6}); verifyData(db1, TABLE_NAME1, 2); verifyData(db2, TABLE_NAME2, 3); db1.close(); verifyData(db2, TABLE_NAME2, 3); db1 = helper.getWritableDatabase(); verifyData(db1, TABLE_NAME1, 2); verifyData(db2, TABLE_NAME2, 3); } @Test public void testCreateAndDropTable() throws Exception { SQLiteDatabase database = helper.getWritableDatabase(); database.execSQL("CREATE TABLE foo(id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT);"); database.execSQL("DROP TABLE IF EXISTS foo;"); } @Test public void testCloseThenOpen() throws Exception { final String TABLE_NAME1 = "fart"; SQLiteDatabase db1 = helper.getWritableDatabase(); setupTable(db1, TABLE_NAME1); insertData(db1, TABLE_NAME1, new int[]{1, 2}); verifyData(db1, TABLE_NAME1, 2); db1.close(); db1 = helper.getWritableDatabase(); assertThat(db1.isOpen()).isTrue(); } private static void assertInitialDB(SQLiteDatabase database, TestOpenHelper helper) { assertDatabaseOpened(database, helper); assertThat(helper.onCreateCalled).isTrue(); } private static void assertSubsequentDB(SQLiteDatabase database, TestOpenHelper helper) { assertDatabaseOpened(database, helper); assertThat(helper.onCreateCalled).isFalse(); } private static void assertDatabaseOpened(SQLiteDatabase database, TestOpenHelper helper) { assertThat(database).isNotNull(); assertThat(database.isOpen()).isTrue(); assertThat(helper.onOpenCalled).isTrue(); assertThat(helper.onUpgradeCalled).isFalse(); } private class TestOpenHelper extends SQLiteOpenHelper { public boolean onCreateCalled; public boolean onUpgradeCalled; public boolean onOpenCalled; public TestOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase database) { onCreateCalled = true; } @Override public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) { onUpgradeCalled = true; } @Override public void onOpen(SQLiteDatabase database) { onOpenCalled = true; } @Override public synchronized void close() { onCreateCalled = false; onUpgradeCalled = false; onOpenCalled = false; super.close(); } } }