1 package org.robolectric.shadows; 2 3 import static com.google.common.truth.Truth.assertThat; 4 5 import android.content.ContentValues; 6 import android.content.Context; 7 import android.database.sqlite.SQLiteDatabase; 8 import android.database.sqlite.SQLiteDatabase.CursorFactory; 9 import android.database.sqlite.SQLiteOpenHelper; 10 import androidx.test.core.app.ApplicationProvider; 11 import androidx.test.ext.junit.runners.AndroidJUnit4; 12 import org.junit.After; 13 import org.junit.Before; 14 import org.junit.Test; 15 import org.junit.runner.RunWith; 16 17 @RunWith(AndroidJUnit4.class) 18 public class SQLiteOpenHelperTest { 19 20 private TestOpenHelper helper; 21 22 @Before setUp()23 public void setUp() throws Exception { 24 helper = new TestOpenHelper(ApplicationProvider.getApplicationContext(), "path", null, 1); 25 } 26 27 @After tearDown()28 public void tearDown() { 29 helper.close(); 30 } 31 32 @Test testConstructorWithNullPathShouldCreateInMemoryDatabase()33 public void testConstructorWithNullPathShouldCreateInMemoryDatabase() throws Exception { 34 TestOpenHelper helper = new TestOpenHelper(null, null, null, 1); 35 SQLiteDatabase database = helper.getReadableDatabase(); 36 assertDatabaseOpened(database, helper); 37 assertInitialDB(database, helper); 38 } 39 40 @Test testInitialGetReadableDatabase()41 public void testInitialGetReadableDatabase() throws Exception { 42 SQLiteDatabase database = helper.getReadableDatabase(); 43 assertInitialDB(database, helper); 44 } 45 46 @Test testSubsequentGetReadableDatabase()47 public void testSubsequentGetReadableDatabase() throws Exception { 48 helper.getReadableDatabase(); 49 helper.close(); 50 SQLiteDatabase database = helper.getReadableDatabase(); 51 52 assertSubsequentDB(database, helper); 53 } 54 55 @Test testSameDBInstanceSubsequentGetReadableDatabase()56 public void testSameDBInstanceSubsequentGetReadableDatabase() throws Exception { 57 SQLiteDatabase db1 = helper.getReadableDatabase(); 58 SQLiteDatabase db2 = helper.getReadableDatabase(); 59 60 assertThat(db1).isSameAs(db2); 61 } 62 63 @Test testInitialGetWritableDatabase()64 public void testInitialGetWritableDatabase() throws Exception { 65 SQLiteDatabase database = helper.getWritableDatabase(); 66 assertInitialDB(database, helper); 67 } 68 69 @Test testSubsequentGetWritableDatabase()70 public void testSubsequentGetWritableDatabase() throws Exception { 71 helper.getWritableDatabase(); 72 helper.close(); 73 74 assertSubsequentDB(helper.getWritableDatabase(), helper); 75 } 76 77 @Test testSameDBInstanceSubsequentGetWritableDatabase()78 public void testSameDBInstanceSubsequentGetWritableDatabase() throws Exception { 79 SQLiteDatabase db1 = helper.getWritableDatabase(); 80 SQLiteDatabase db2 = helper.getWritableDatabase(); 81 82 assertThat(db1).isSameAs(db2); 83 } 84 85 @Test testClose()86 public void testClose() throws Exception { 87 SQLiteDatabase database = helper.getWritableDatabase(); 88 89 assertThat(database.isOpen()).isTrue(); 90 helper.close(); 91 assertThat(database.isOpen()).isFalse(); 92 } 93 94 @Test testGetPath()95 public void testGetPath() throws Exception { 96 final String path1 = "path1", path2 = "path2"; 97 98 TestOpenHelper helper1 = 99 new TestOpenHelper(ApplicationProvider.getApplicationContext(), path1, null, 1); 100 String expectedPath1 = 101 ApplicationProvider.getApplicationContext().getDatabasePath(path1).getAbsolutePath(); 102 assertThat(helper1.getReadableDatabase().getPath()).isEqualTo(expectedPath1); 103 104 TestOpenHelper helper2 = 105 new TestOpenHelper(ApplicationProvider.getApplicationContext(), path2, null, 1); 106 String expectedPath2 = 107 ApplicationProvider.getApplicationContext().getDatabasePath(path2).getAbsolutePath(); 108 assertThat(helper2.getReadableDatabase().getPath()).isEqualTo(expectedPath2); 109 } 110 111 @Test testCloseMultipleDbs()112 public void testCloseMultipleDbs() throws Exception { 113 TestOpenHelper helper2 = 114 new TestOpenHelper(ApplicationProvider.getApplicationContext(), "path2", null, 1); 115 SQLiteDatabase database1 = helper.getWritableDatabase(); 116 SQLiteDatabase database2 = helper2.getWritableDatabase(); 117 assertThat(database1.isOpen()).isTrue(); 118 assertThat(database2.isOpen()).isTrue(); 119 helper.close(); 120 assertThat(database1.isOpen()).isFalse(); 121 assertThat(database2.isOpen()).isTrue(); 122 helper2.close(); 123 assertThat(database2.isOpen()).isFalse(); 124 } 125 126 @Test testOpenMultipleDbsOnCreate()127 public void testOpenMultipleDbsOnCreate() throws Exception { 128 TestOpenHelper helper2 = 129 new TestOpenHelper(ApplicationProvider.getApplicationContext(), "path2", null, 1); 130 assertThat(helper.onCreateCalled).isFalse(); 131 assertThat(helper2.onCreateCalled).isFalse(); 132 helper.getWritableDatabase(); 133 assertThat(helper.onCreateCalled).isTrue(); 134 assertThat(helper2.onCreateCalled).isFalse(); 135 helper2.getWritableDatabase(); 136 assertThat(helper.onCreateCalled).isTrue(); 137 assertThat(helper2.onCreateCalled).isTrue(); 138 helper.close(); 139 helper2.close(); 140 } 141 setupTable(SQLiteDatabase db, String table)142 private void setupTable(SQLiteDatabase db, String table) { 143 db.execSQL("CREATE TABLE " + table + " (" + 144 "id INTEGER PRIMARY KEY AUTOINCREMENT, " + 145 "testVal INTEGER DEFAULT 0" + 146 ");"); 147 } insertData(SQLiteDatabase db, String table, int[] values)148 private void insertData(SQLiteDatabase db, String table, int[] values) { 149 for (int i : values) { 150 ContentValues cv = new ContentValues(); 151 cv.put("testVal", i); 152 db.insert(table, null, cv); 153 } 154 } 155 verifyData(SQLiteDatabase db, String table, int expectedVals)156 private void verifyData(SQLiteDatabase db, String table, int expectedVals) { 157 assertThat(db.query(table, null, null, null, 158 null, null, null).getCount()).isEqualTo(expectedVals); 159 } 160 161 @Test testMultipleDbsPreserveData()162 public void testMultipleDbsPreserveData() throws Exception { 163 final String TABLE_NAME1 = "fart", TABLE_NAME2 = "fart2"; 164 SQLiteDatabase db1 = helper.getWritableDatabase(); 165 setupTable(db1, TABLE_NAME1); 166 insertData(db1, TABLE_NAME1, new int[]{1, 2}); 167 TestOpenHelper helper2 = 168 new TestOpenHelper(ApplicationProvider.getApplicationContext(), "path2", null, 1); 169 SQLiteDatabase db2 = helper2.getWritableDatabase(); 170 setupTable(db2, TABLE_NAME2); 171 insertData(db2, TABLE_NAME2, new int[]{4, 5, 6}); 172 verifyData(db1, TABLE_NAME1, 2); 173 verifyData(db2, TABLE_NAME2, 3); 174 } 175 176 @Test testCloseOneDbKeepsDataForOther()177 public void testCloseOneDbKeepsDataForOther() throws Exception { 178 final String TABLE_NAME1 = "fart", TABLE_NAME2 = "fart2"; 179 TestOpenHelper helper2 = 180 new TestOpenHelper(ApplicationProvider.getApplicationContext(), "path2", null, 1); 181 SQLiteDatabase db1 = helper.getWritableDatabase(); 182 SQLiteDatabase db2 = helper2.getWritableDatabase(); 183 setupTable(db1, TABLE_NAME1); 184 setupTable(db2, TABLE_NAME2); 185 insertData(db1, TABLE_NAME1, new int[]{1, 2}); 186 insertData(db2, TABLE_NAME2, new int[]{4, 5, 6}); 187 verifyData(db1, TABLE_NAME1, 2); 188 verifyData(db2, TABLE_NAME2, 3); 189 db1.close(); 190 verifyData(db2, TABLE_NAME2, 3); 191 db1 = helper.getWritableDatabase(); 192 verifyData(db1, TABLE_NAME1, 2); 193 verifyData(db2, TABLE_NAME2, 3); 194 } 195 196 @Test testCreateAndDropTable()197 public void testCreateAndDropTable() throws Exception { 198 SQLiteDatabase database = helper.getWritableDatabase(); 199 database.execSQL("CREATE TABLE foo(id INTEGER PRIMARY KEY AUTOINCREMENT, data TEXT);"); 200 database.execSQL("DROP TABLE IF EXISTS foo;"); 201 } 202 203 @Test testCloseThenOpen()204 public void testCloseThenOpen() throws Exception { 205 final String TABLE_NAME1 = "fart"; 206 SQLiteDatabase db1 = helper.getWritableDatabase(); 207 setupTable(db1, TABLE_NAME1); 208 insertData(db1, TABLE_NAME1, new int[]{1, 2}); 209 verifyData(db1, TABLE_NAME1, 2); 210 db1.close(); 211 db1 = helper.getWritableDatabase(); 212 assertThat(db1.isOpen()).isTrue(); 213 } 214 assertInitialDB(SQLiteDatabase database, TestOpenHelper helper)215 private static void assertInitialDB(SQLiteDatabase database, TestOpenHelper helper) { 216 assertDatabaseOpened(database, helper); 217 assertThat(helper.onCreateCalled).isTrue(); 218 } 219 assertSubsequentDB(SQLiteDatabase database, TestOpenHelper helper)220 private static void assertSubsequentDB(SQLiteDatabase database, TestOpenHelper helper) { 221 assertDatabaseOpened(database, helper); 222 assertThat(helper.onCreateCalled).isFalse(); 223 } 224 assertDatabaseOpened(SQLiteDatabase database, TestOpenHelper helper)225 private static void assertDatabaseOpened(SQLiteDatabase database, TestOpenHelper helper) { 226 assertThat(database).isNotNull(); 227 assertThat(database.isOpen()).isTrue(); 228 assertThat(helper.onOpenCalled).isTrue(); 229 assertThat(helper.onUpgradeCalled).isFalse(); 230 } 231 232 private static class TestOpenHelper extends SQLiteOpenHelper { 233 public boolean onCreateCalled; 234 public boolean onUpgradeCalled; 235 public boolean onOpenCalled; 236 TestOpenHelper(Context context, String name, CursorFactory factory, int version)237 public TestOpenHelper(Context context, String name, CursorFactory factory, int version) { 238 super(context, name, factory, version); 239 } 240 241 @Override onCreate(SQLiteDatabase database)242 public void onCreate(SQLiteDatabase database) { 243 onCreateCalled = true; 244 } 245 246 @Override onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion)247 public void onUpgrade(SQLiteDatabase database, int oldVersion, int newVersion) { 248 onUpgradeCalled = true; 249 } 250 251 @Override onOpen(SQLiteDatabase database)252 public void onOpen(SQLiteDatabase database) { 253 onOpenCalled = true; 254 } 255 256 @Override close()257 public synchronized void close() { 258 onCreateCalled = false; 259 onUpgradeCalled = false; 260 onOpenCalled = false; 261 262 super.close(); 263 } 264 } 265 } 266