1bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori/* 2bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * Copyright (C) 2010 The Android Open Source Project 3bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * 4bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * Licensed under the Apache License, Version 2.0 (the "License"); 5bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * you may not use this file except in compliance with the License. 6bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * You may obtain a copy of the License at 7bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * 8bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * http://www.apache.org/licenses/LICENSE-2.0 9bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * 10bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * Unless required by applicable law or agreed to in writing, software 11bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * distributed under the License is distributed on an "AS IS" BASIS, 12bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * See the License for the specific language governing permissions and 14bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * limitations under the License. 15bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori */ 16bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 17bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noripackage android.database; 18bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 19bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noriimport android.content.Context; 20bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noriimport android.database.sqlite.SQLiteDatabase; 21e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Noriimport android.database.sqlite.SQLiteDiskIOException; 22bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noriimport android.database.sqlite.SQLiteException; 23bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noriimport android.test.AndroidTestCase; 24bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noriimport android.util.Log; 25bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 26bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noriimport java.io.BufferedWriter; 27bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noriimport java.io.File; 28bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noriimport java.io.FileWriter; 29bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noriimport java.io.IOException; 30bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 31bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Noripublic class DatabaseErrorHandlerTest extends AndroidTestCase { 32bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 33bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori private SQLiteDatabase mDatabase; 34bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori private File mDatabaseFile; 35bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori private static final String DB_NAME = "database_test.db"; 36bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori private File dbDir; 37bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 38bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori @Override 39bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori protected void setUp() throws Exception { 40bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori super.setUp(); 41bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori dbDir = getContext().getDir(this.getClass().getName(), Context.MODE_PRIVATE); 42bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori mDatabaseFile = new File(dbDir, DB_NAME); 43bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori if (mDatabaseFile.exists()) { 44bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori mDatabaseFile.delete(); 45bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 46bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori mDatabase = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null, 47bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori new MyDatabaseCorruptionHandler()); 48bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori assertNotNull(mDatabase); 49bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 50bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 51bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori @Override 52bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori protected void tearDown() throws Exception { 53bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori mDatabase.close(); 54bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori mDatabaseFile.delete(); 55bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori super.tearDown(); 56bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 57bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 58bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori public void testNoCorruptionCase() { 59bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori new MyDatabaseCorruptionHandler().onCorruption(mDatabase); 60bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // database file should still exist 61bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori assertTrue(mDatabaseFile.exists()); 62bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 63bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 64e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori 65bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori public void testDatabaseIsCorrupt() throws IOException { 66bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori mDatabase.execSQL("create table t (i int);"); 67bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // write junk into the database file 68bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori BufferedWriter writer = new BufferedWriter(new FileWriter(mDatabaseFile.getPath())); 69bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori writer.write("blah"); 70bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori writer.close(); 71bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori assertTrue(mDatabaseFile.exists()); 72bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // since the database file is now corrupt, doing any sql on this database connection 73bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // should trigger call to MyDatabaseCorruptionHandler.onCorruption 74bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori try { 75bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori mDatabase.execSQL("select * from t;"); 76bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori fail("expected exception"); 77e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori } catch (SQLiteDiskIOException e) { 78e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori /** 79e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori * this test used to produce a corrupted db. but with new sqlite it instead reports 80e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori * Disk I/O error. meh.. 81e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori * need to figure out how to cause corruption in db 82e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori */ 83bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // expected 84e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori if (mDatabaseFile.exists()) { 85e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori mDatabaseFile.delete(); 86e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori } 87e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori } catch (SQLiteException e) { 88e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori 89bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 90e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori // database file should be gone 91e7dea4ec2479002f5ee15bc6fc98d8c8acd123a6Vasu Nori assertFalse(mDatabaseFile.exists()); 92bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // after corruption handler is called, the database file should be free of 93bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // database corruption 94bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(mDatabaseFile.getPath(), null, 95bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori new MyDatabaseCorruptionHandler()); 96bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori assertTrue(db.isDatabaseIntegrityOk()); 97bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 98bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori 99bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori /** 100bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * An example implementation of {@link DatabaseErrorHandler} to demonstrate 101bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * database corruption handler which checks to make sure database is indeed 102bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori * corrupt before deleting the file. 103bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori */ 104bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori public class MyDatabaseCorruptionHandler implements DatabaseErrorHandler { 105bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori public void onCorruption(SQLiteDatabase dbObj) { 106bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori boolean databaseOk = dbObj.isDatabaseIntegrityOk(); 107bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // close the database 108bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori try { 109bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori dbObj.close(); 110bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } catch (SQLiteException e) { 111bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori /* ignore */ 112bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 113bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori if (databaseOk) { 114bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // database is just fine. no need to delete the database file 115bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori Log.e("MyDatabaseCorruptionHandler", "no corruption in the database: " + 116bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori mDatabaseFile.getPath()); 117bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } else { 118bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori // database is corrupt. delete the database file 119bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori Log.e("MyDatabaseCorruptionHandler", "deleting the database file: " + 120bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori mDatabaseFile.getPath()); 121bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori new File(dbDir, DB_NAME).delete(); 122bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 123bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 124bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori } 125bfe1dc27944c80dcb81f0eb313987999ecd7b6faVasu Nori}