1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.launcher3.model; 17 18 import static junit.framework.Assert.assertEquals; 19 import static junit.framework.Assert.assertFalse; 20 import static junit.framework.Assert.assertNotSame; 21 import static junit.framework.Assert.assertTrue; 22 23 import android.content.ContentValues; 24 import android.content.Context; 25 import android.database.Cursor; 26 import android.database.sqlite.SQLiteDatabase; 27 import android.database.sqlite.SQLiteOpenHelper; 28 import android.support.test.InstrumentationRegistry; 29 import android.support.test.filters.SmallTest; 30 import android.support.test.runner.AndroidJUnit4; 31 32 import com.android.launcher3.LauncherProvider; 33 import com.android.launcher3.LauncherProvider.DatabaseHelper; 34 import com.android.launcher3.LauncherSettings.Favorites; 35 import com.android.launcher3.R; 36 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 41 import java.io.File; 42 43 /** 44 * Tests for {@link DbDowngradeHelper} 45 */ 46 @SmallTest 47 @RunWith(AndroidJUnit4.class) 48 public class DbDowngradeHelperTest { 49 50 private static final String SCHEMA_FILE = "test_schema.json"; 51 private static final String DB_FILE = "test.db"; 52 53 private Context mContext; 54 private File mSchemaFile; 55 private File mDbFile; 56 57 @Before setup()58 public void setup() { 59 mContext = InstrumentationRegistry.getTargetContext(); 60 mSchemaFile = mContext.getFileStreamPath(SCHEMA_FILE); 61 mDbFile = mContext.getDatabasePath(DB_FILE); 62 } 63 64 @Test testUpdateSchemaFile()65 public void testUpdateSchemaFile() throws Exception { 66 Context myContext = InstrumentationRegistry.getContext(); 67 int testResId = myContext.getResources().getIdentifier( 68 "db_schema_v10", "raw", myContext.getPackageName()); 69 mSchemaFile.delete(); 70 assertFalse(mSchemaFile.exists()); 71 72 DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, myContext, testResId); 73 assertTrue(mSchemaFile.exists()); 74 assertEquals(10, DbDowngradeHelper.parse(mSchemaFile).version); 75 76 // Schema is updated on version upgrade 77 assertTrue(mSchemaFile.setLastModified(0)); 78 DbDowngradeHelper.updateSchemaFile(mSchemaFile, 11, myContext, testResId); 79 assertNotSame(0, mSchemaFile.lastModified()); 80 81 // Schema is not updated when version is same 82 assertTrue(mSchemaFile.setLastModified(0)); 83 DbDowngradeHelper.updateSchemaFile(mSchemaFile, 10, myContext, testResId); 84 assertEquals(0, mSchemaFile.lastModified()); 85 86 // Schema is not updated on version downgrade 87 DbDowngradeHelper.updateSchemaFile(mSchemaFile, 3, myContext, testResId); 88 assertEquals(0, mSchemaFile.lastModified()); 89 } 90 91 @Test testDowngrade_success_v24()92 public void testDowngrade_success_v24() throws Exception { 93 setupTestDb(); 94 95 TestOpenHelper helper = new TestOpenHelper(24); 96 assertEquals(24, helper.getReadableDatabase().getVersion()); 97 helper.close(); 98 } 99 100 @Test testDowngrade_success_v22()101 public void testDowngrade_success_v22() throws Exception { 102 setupTestDb(); 103 104 SQLiteOpenHelper helper = new TestOpenHelper(22); 105 assertEquals(22, helper.getWritableDatabase().getVersion()); 106 107 // Check column does not exist 108 try (Cursor c = helper.getWritableDatabase().query(Favorites.TABLE_NAME, 109 null, null, null, null, null, null)) { 110 assertEquals(-1, c.getColumnIndex(Favorites.OPTIONS)); 111 112 // Check data is present 113 assertEquals(10, c.getCount()); 114 } 115 helper.close(); 116 117 helper = new DatabaseHelper(mContext, null, DB_FILE) { 118 @Override 119 public void onOpen(SQLiteDatabase db) { } 120 }; 121 assertEquals(LauncherProvider.SCHEMA_VERSION, helper.getWritableDatabase().getVersion()); 122 123 try (Cursor c = helper.getWritableDatabase().query(Favorites.TABLE_NAME, 124 null, null, null, null, null, null)) { 125 // Check column exists 126 assertNotSame(-1, c.getColumnIndex(Favorites.OPTIONS)); 127 128 // Check data is present 129 assertEquals(10, c.getCount()); 130 } 131 helper.close(); 132 } 133 134 @Test(expected = DowngradeFailException.class) testDowngrade_fail_v20()135 public void testDowngrade_fail_v20() throws Exception { 136 setupTestDb(); 137 138 TestOpenHelper helper = new TestOpenHelper(20); 139 helper.getReadableDatabase().getVersion(); 140 } 141 setupTestDb()142 private void setupTestDb() throws Exception { 143 mSchemaFile.delete(); 144 mDbFile.delete(); 145 146 DbDowngradeHelper.updateSchemaFile(mSchemaFile, LauncherProvider.SCHEMA_VERSION, mContext, 147 R.raw.downgrade_schema); 148 149 DatabaseHelper dbHelper = new DatabaseHelper(mContext, null, DB_FILE) { 150 @Override 151 public void onOpen(SQLiteDatabase db) { } 152 }; 153 // Insert dummy data 154 for (int i = 0; i < 10; i++) { 155 ContentValues values = new ContentValues(); 156 values.put(Favorites._ID, i); 157 values.put(Favorites.TITLE, "title " + i); 158 dbHelper.getWritableDatabase().insert(Favorites.TABLE_NAME, null, values); 159 } 160 dbHelper.close(); 161 } 162 163 private class TestOpenHelper extends SQLiteOpenHelper { 164 TestOpenHelper(int version)165 public TestOpenHelper(int version) { 166 super(mContext, DB_FILE, null, version); 167 } 168 169 @Override onCreate(SQLiteDatabase sqLiteDatabase)170 public void onCreate(SQLiteDatabase sqLiteDatabase) { 171 throw new RuntimeException("DB should already be created"); 172 } 173 174 @Override onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)175 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 176 throw new RuntimeException("Only downgrade supported"); 177 } 178 179 @Override onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion)180 public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 181 try { 182 DbDowngradeHelper.parse(mSchemaFile).onDowngrade(db, oldVersion, newVersion); 183 } catch (Exception e) { 184 throw new DowngradeFailException(e); 185 } 186 } 187 } 188 189 private static class DowngradeFailException extends RuntimeException { DowngradeFailException(Exception e)190 public DowngradeFailException(Exception e) { 191 super(e); 192 } 193 } 194 } 195