private static RuntimeException getSqliteException(final String message, final int baseErrorCode) { // Mapping is from throw_sqlite3_exception in android_database_SQLiteCommon.cpp switch (baseErrorCode) { case SQLiteConstants.SQLITE_ABORT: return new SQLiteAbortException(message); case SQLiteConstants.SQLITE_PERM: return new SQLiteAccessPermException(message); case SQLiteConstants.SQLITE_RANGE: return new SQLiteBindOrColumnIndexOutOfRangeException(message); case SQLiteConstants.SQLITE_TOOBIG: return new SQLiteBlobTooBigException(message); case SQLiteConstants.SQLITE_CANTOPEN: return new SQLiteCantOpenDatabaseException(message); case SQLiteConstants.SQLITE_CONSTRAINT: return new SQLiteConstraintException(message); case SQLiteConstants.SQLITE_NOTADB: // fall through case SQLiteConstants.SQLITE_CORRUPT: return new SQLiteDatabaseCorruptException(message); case SQLiteConstants.SQLITE_BUSY: return new SQLiteDatabaseLockedException(message); case SQLiteConstants.SQLITE_MISMATCH: return new SQLiteDatatypeMismatchException(message); case SQLiteConstants.SQLITE_IOERR: return new SQLiteDiskIOException(message); case SQLiteConstants.SQLITE_DONE: return new SQLiteDoneException(message); case SQLiteConstants.SQLITE_FULL: return new SQLiteFullException(message); case SQLiteConstants.SQLITE_MISUSE: return new SQLiteMisuseException(message); case SQLiteConstants.SQLITE_NOMEM: return new SQLiteOutOfMemoryException(message); case SQLiteConstants.SQLITE_READONLY: return new SQLiteReadOnlyDatabaseException(message); case SQLiteConstants.SQLITE_LOCKED: return new SQLiteTableLockedException(message); case SQLiteConstants.SQLITE_INTERRUPT: return new OperationCanceledException(message); default: return new android.database.sqlite.SQLiteException(message + ", base error code: " + baseErrorCode); } } }
@Test public void failsToDeleteLogDuringPutWhenFull() { /* Mocking instances. */ Context contextMock = mock(Context.class); SQLiteOpenHelper helperMock = mock(SQLiteOpenHelper.class); SQLiteDatabase sqLiteDatabase = mock(SQLiteDatabase.class); when(helperMock.getWritableDatabase()).thenReturn(sqLiteDatabase); /* Mock the select cursor we are using to find logs to evict to fail. */ mockStatic(SQLiteUtils.class); Cursor cursor = mock(Cursor.class); SQLiteDiskIOException fatalException = new SQLiteDiskIOException(); when(cursor.moveToNext()).thenThrow(fatalException); SQLiteQueryBuilder sqLiteQueryBuilder = mock(SQLiteQueryBuilder.class, new Returns(cursor)); when(SQLiteUtils.newSQLiteQueryBuilder()).thenReturn(sqLiteQueryBuilder); /* Simulate that database is full and that deletes fail because of the cursor. */ when(sqLiteDatabase.insertOrThrow(anyString(), anyString(), any(ContentValues.class))).thenThrow(new SQLiteFullException()); /* Instantiate real instance for DatabaseManager. */ DatabaseManager databaseManager = spy(new DatabaseManager(contextMock, "database", "table", 1, null, null)); databaseManager.setSQLiteOpenHelper(helperMock); /* When we put a log, it will fail to purge. */ assertEquals(-1, databaseManager.put(mock(ContentValues.class), "priority")); }
@Test public void cursorFailsToCloseAfterPut() { /* Mocking instances. */ Context contextMock = mock(Context.class); SQLiteOpenHelper helperMock = mock(SQLiteOpenHelper.class); SQLiteDatabase sqLiteDatabase = mock(SQLiteDatabase.class); when(helperMock.getWritableDatabase()).thenReturn(sqLiteDatabase); /* Mock the select cursor we are using to find logs to evict to fail. */ mockStatic(SQLiteUtils.class); Cursor cursor = mock(Cursor.class); SQLiteDiskIOException exception = new SQLiteDiskIOException(); doThrow(exception).when(cursor).close(); when(cursor.moveToNext()).thenReturn(true).thenReturn(false); SQLiteQueryBuilder sqLiteQueryBuilder = mock(SQLiteQueryBuilder.class, new Returns(cursor)); when(SQLiteUtils.newSQLiteQueryBuilder()).thenReturn(sqLiteQueryBuilder); /* Simulate that database is full only once (will work after purging 1 log). */ when(sqLiteDatabase.insertOrThrow(anyString(), anyString(), any(ContentValues.class))).thenThrow(new SQLiteFullException()).thenReturn(1L); /* Instantiate real instance for DatabaseManager. */ DatabaseManager databaseManager = spy(new DatabaseManager(contextMock, "database", "table", 1, null, null)); databaseManager.setSQLiteOpenHelper(helperMock); /* When we put a log, it succeeds even if a problem occurred while closing purge cursor. */ long id = databaseManager.put(mock(ContentValues.class), "priority"); assertEquals(1, id); } }
when(failingCursor.moveToNext()).thenThrow(new SQLiteDiskIOException()); when(databaseManager.getCursor(any(SQLiteQueryBuilder.class), isNotNull(String[].class), any(String[].class), anyString())).thenReturn(failingCursor);
private RuntimeException getSqliteException(String message, int baseErrorCode) { // Mapping is from throw_sqlite3_exception in android_database_SQLiteCommon.cpp switch (baseErrorCode) { case SQLiteConstants.SQLITE_ABORT: return new SQLiteAbortException(message); case SQLiteConstants.SQLITE_PERM: return new SQLiteAccessPermException(message); case SQLiteConstants.SQLITE_RANGE: return new SQLiteBindOrColumnIndexOutOfRangeException(message); case SQLiteConstants.SQLITE_TOOBIG: return new SQLiteBlobTooBigException(message); case SQLiteConstants.SQLITE_CANTOPEN: return new SQLiteCantOpenDatabaseException(message); case SQLiteConstants.SQLITE_CONSTRAINT: return new SQLiteConstraintException(message); case SQLiteConstants.SQLITE_NOTADB: // fall through case SQLiteConstants.SQLITE_CORRUPT: return new SQLiteDatabaseCorruptException(message); case SQLiteConstants.SQLITE_BUSY: return new SQLiteDatabaseLockedException(message); case SQLiteConstants.SQLITE_MISMATCH: return new SQLiteDatatypeMismatchException(message); case SQLiteConstants.SQLITE_IOERR: return new SQLiteDiskIOException(message); case SQLiteConstants.SQLITE_DONE: return new SQLiteDoneException(message); case SQLiteConstants.SQLITE_FULL: return new SQLiteFullException(message); case SQLiteConstants.SQLITE_MISUSE: return new SQLiteMisuseException(message); case SQLiteConstants.SQLITE_NOMEM: return new SQLiteOutOfMemoryException(message); case SQLiteConstants.SQLITE_READONLY: return new SQLiteReadOnlyDatabaseException(message); case SQLiteConstants.SQLITE_LOCKED: return new SQLiteTableLockedException(message); case SQLiteConstants.SQLITE_INTERRUPT: return new OperationCanceledException(message); default: return new android.database.sqlite.SQLiteException(message + ", base error code: " + baseErrorCode); } } }
private RuntimeException getSqliteException(String message, int baseErrorCode) { // Mapping is from throw_sqlite3_exception in android_database_SQLiteCommon.cpp switch (baseErrorCode) { case SQLiteConstants.SQLITE_ABORT: return new SQLiteAbortException(message); case SQLiteConstants.SQLITE_PERM: return new SQLiteAccessPermException(message); case SQLiteConstants.SQLITE_RANGE: return new SQLiteBindOrColumnIndexOutOfRangeException(message); case SQLiteConstants.SQLITE_TOOBIG: return new SQLiteBlobTooBigException(message); case SQLiteConstants.SQLITE_CANTOPEN: return new SQLiteCantOpenDatabaseException(message); case SQLiteConstants.SQLITE_CONSTRAINT: return new SQLiteConstraintException(message); case SQLiteConstants.SQLITE_NOTADB: // fall through case SQLiteConstants.SQLITE_CORRUPT: return new SQLiteDatabaseCorruptException(message); case SQLiteConstants.SQLITE_BUSY: return new SQLiteDatabaseLockedException(message); case SQLiteConstants.SQLITE_MISMATCH: return new SQLiteDatatypeMismatchException(message); case SQLiteConstants.SQLITE_IOERR: return new SQLiteDiskIOException(message); case SQLiteConstants.SQLITE_DONE: return new SQLiteDoneException(message); case SQLiteConstants.SQLITE_FULL: return new SQLiteFullException(message); case SQLiteConstants.SQLITE_MISUSE: return new SQLiteMisuseException(message); case SQLiteConstants.SQLITE_NOMEM: return new SQLiteOutOfMemoryException(message); case SQLiteConstants.SQLITE_READONLY: return new SQLiteReadOnlyDatabaseException(message); case SQLiteConstants.SQLITE_LOCKED: return new SQLiteTableLockedException(message); case SQLiteConstants.SQLITE_INTERRUPT: return new OperationCanceledException(message); default: return new android.database.sqlite.SQLiteException(message + ", base error code: " + baseErrorCode); } } }
private static RuntimeException getSqliteException(final String message, final int baseErrorCode) { // Mapping is from throw_sqlite3_exception in android_database_SQLiteCommon.cpp switch (baseErrorCode) { case SQLiteConstants.SQLITE_ABORT: return new SQLiteAbortException(message); case SQLiteConstants.SQLITE_PERM: return new SQLiteAccessPermException(message); case SQLiteConstants.SQLITE_RANGE: return new SQLiteBindOrColumnIndexOutOfRangeException(message); case SQLiteConstants.SQLITE_TOOBIG: return new SQLiteBlobTooBigException(message); case SQLiteConstants.SQLITE_CANTOPEN: return new SQLiteCantOpenDatabaseException(message); case SQLiteConstants.SQLITE_CONSTRAINT: return new SQLiteConstraintException(message); case SQLiteConstants.SQLITE_NOTADB: // fall through case SQLiteConstants.SQLITE_CORRUPT: return new SQLiteDatabaseCorruptException(message); case SQLiteConstants.SQLITE_BUSY: return new SQLiteDatabaseLockedException(message); case SQLiteConstants.SQLITE_MISMATCH: return new SQLiteDatatypeMismatchException(message); case SQLiteConstants.SQLITE_IOERR: return new SQLiteDiskIOException(message); case SQLiteConstants.SQLITE_DONE: return new SQLiteDoneException(message); case SQLiteConstants.SQLITE_FULL: return new SQLiteFullException(message); case SQLiteConstants.SQLITE_MISUSE: return new SQLiteMisuseException(message); case SQLiteConstants.SQLITE_NOMEM: return new SQLiteOutOfMemoryException(message); case SQLiteConstants.SQLITE_READONLY: return new SQLiteReadOnlyDatabaseException(message); case SQLiteConstants.SQLITE_LOCKED: return new SQLiteTableLockedException(message); case SQLiteConstants.SQLITE_INTERRUPT: return new OperationCanceledException(message); default: return new android.database.sqlite.SQLiteException(message + ", base error code: " + baseErrorCode); } } }
private static RuntimeException getSqliteException(final String message, final int baseErrorCode) { // Mapping is from throw_sqlite3_exception in android_database_SQLiteCommon.cpp switch (baseErrorCode) { case SQLiteConstants.SQLITE_ABORT: return new SQLiteAbortException(message); case SQLiteConstants.SQLITE_PERM: return new SQLiteAccessPermException(message); case SQLiteConstants.SQLITE_RANGE: return new SQLiteBindOrColumnIndexOutOfRangeException(message); case SQLiteConstants.SQLITE_TOOBIG: return new SQLiteBlobTooBigException(message); case SQLiteConstants.SQLITE_CANTOPEN: return new SQLiteCantOpenDatabaseException(message); case SQLiteConstants.SQLITE_CONSTRAINT: return new SQLiteConstraintException(message); case SQLiteConstants.SQLITE_NOTADB: // fall through case SQLiteConstants.SQLITE_CORRUPT: return new SQLiteDatabaseCorruptException(message); case SQLiteConstants.SQLITE_BUSY: return new SQLiteDatabaseLockedException(message); case SQLiteConstants.SQLITE_MISMATCH: return new SQLiteDatatypeMismatchException(message); case SQLiteConstants.SQLITE_IOERR: return new SQLiteDiskIOException(message); case SQLiteConstants.SQLITE_DONE: return new SQLiteDoneException(message); case SQLiteConstants.SQLITE_FULL: return new SQLiteFullException(message); case SQLiteConstants.SQLITE_MISUSE: return new SQLiteMisuseException(message); case SQLiteConstants.SQLITE_NOMEM: return new SQLiteOutOfMemoryException(message); case SQLiteConstants.SQLITE_READONLY: return new SQLiteReadOnlyDatabaseException(message); case SQLiteConstants.SQLITE_LOCKED: return new SQLiteTableLockedException(message); case SQLiteConstants.SQLITE_INTERRUPT: return new OperationCanceledException(message); default: return new android.database.sqlite.SQLiteException(message + ", base error code: " + baseErrorCode); } } }
@Test public void testDiskIoErrorCatching() throws InterruptedException { final String method = "testDiskIoErrorCatching"; MyLog.i(this, method + " started"); mService.setListenedCommand(CommandData.newAccountCommand( CommandEnum.RATE_LIMIT_STATUS, demoData.getGnuSocialAccount())); mService.getHttp().setRuntimeException(new SQLiteDiskIOException(method)); long startCount = mService.executionStartCount; mService.sendListenedCommand(); mService.assertCommandExecutionStarted("First command", startCount, TriState.TRUE); assertTrue("Service stopped", mService.waitForServiceStopped(true)); assertEquals("No DiskIoException", 1, ExceptionsCounter.getDiskIoExceptionsCount()); DbUtils.waitMs(method, 3000); MyLog.i(this, method + " ended"); } }