Skip to content

Commit e3d1dd2

Browse files
Merge pull request #9 from brodybits/cb-test-custom-corruption-handler
Test changes for custom database corruption error handler
2 parents f8a0de9 + 5fcef62 commit e3d1dd2

File tree

4 files changed

+484
-8
lines changed

4 files changed

+484
-8
lines changed

src/main/java/net/zetetic/tests/ClosedDatabaseTest.java

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import java.util.Locale;
99

10+
import net.sqlcipher.DatabaseErrorHandler;
1011
import net.sqlcipher.database.SQLiteDatabase;
1112
import net.sqlcipher.database.SQLiteException;
1213
import net.zetetic.ZeteticApplication;
@@ -29,12 +30,12 @@ public TestResult run() {
2930
@Override
3031
public boolean execute(SQLiteDatabase null_database_ignored) {
3132

32-
File testDatabasePath = ZeteticApplication.getInstance().getDatabasePath("closed-db-test.db");
33+
File closedDatabasePath = ZeteticApplication.getInstance().getDatabasePath("closed-db-test.db");
3334

3435
boolean status = false;
3536

3637
try {
37-
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(testDatabasePath, "", null);
38+
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(closedDatabasePath, "", null);
3839

3940
database.close();
4041

@@ -45,7 +46,58 @@ public boolean execute(SQLiteDatabase null_database_ignored) {
4546
return false;
4647
}
4748
finally {
48-
testDatabasePath.delete();
49+
closedDatabasePath.delete();
50+
}
51+
52+
if (!status) return false;
53+
54+
status = false;
55+
56+
final File corruptDatabase = ZeteticApplication.getInstance().getDatabasePath("corrupt.db");
57+
58+
// run closed database tests again in custom DatabaseErrorHandler:
59+
try {
60+
ZeteticApplication.getInstance().extractAssetToDatabaseDirectory("corrupt.db");
61+
62+
// ugly trick from: http://stackoverflow.com/questions/5977735/setting-outer-variable-from-anonymous-inner-class
63+
final boolean[] inner_status_slot = new boolean[1];
64+
65+
// on a database object that was NEVER actually opened (due to a corrupt database file):
66+
SQLiteDatabase database = SQLiteDatabase.openDatabase(corruptDatabase.getPath(), "", null, SQLiteDatabase.CREATE_IF_NECESSARY, null, new DatabaseErrorHandler() {
67+
@Override
68+
public void onCorruption(SQLiteDatabase db) {
69+
try {
70+
inner_status_slot[0] = execute_closed_database_tests(db);
71+
} catch (Exception ex) {
72+
// Uncaught exception (not expected):
73+
Log.e(TAG, "UNEXPECTED EXCEPTION", ex);
74+
}
75+
76+
try {
77+
corruptDatabase.delete();
78+
} catch (Exception ex) {
79+
// Uncaught exception (not expected):
80+
Log.e(TAG, "UNEXPECTED EXCEPTION", ex);
81+
}
82+
}
83+
});
84+
85+
status = inner_status_slot[0];
86+
87+
// NOTE: database not expected to be null, but double-check:
88+
if (database == null) {
89+
Log.e(TAG, "ERROR: got null database object");
90+
return false;
91+
}
92+
93+
database.close();
94+
} catch (Exception ex) {
95+
// Uncaught exception (not expected):
96+
Log.e(TAG, "UNEXPECTED EXCEPTION", ex);
97+
return false;
98+
}
99+
finally {
100+
corruptDatabase.delete();
49101
}
50102

51103
return status;
@@ -257,9 +309,8 @@ boolean execute_closed_database_tests(SQLiteDatabase database) {
257309
Log.v(ZeteticApplication.TAG, "SQLiteDatabase.markTableSyncable(String, String) did throw exception on closed database OK", e);
258310
}
259311

260-
// TBD SQLiteDatabase.markTableSyncable(String, String, String) does NOT throw exception on closed database:
261312
try {
262-
// NOTE: does not (yet) throw an exception on a closed database:
313+
// [should] throw an exception on a closed database:
263314
database.markTableSyncable("aa", "bb", "cc");
264315

265316
// ...
@@ -297,6 +348,10 @@ boolean execute_closed_database_tests(SQLiteDatabase database) {
297348
database.setLockingEnabled(false);
298349
database.setLockingEnabled(true);
299350

351+
database.inTransaction();
352+
database.isDbLockedByCurrentThread();
353+
database.isDbLockedByOtherThreads();
354+
300355
database.close();
301356

302357
database.isReadOnly();

src/main/java/net/zetetic/tests/CorruptDatabaseTest.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import android.database.Cursor;
66

77
import net.sqlcipher.database.SQLiteDatabase;
8+
import net.sqlcipher.database.SQLiteDatabaseCorruptException;
89

910
import net.zetetic.ZeteticApplication;
1011

@@ -36,13 +37,39 @@ public boolean execute(SQLiteDatabase null_database_ignored) {
3637

3738
SQLiteDatabase database = SQLiteDatabase.openOrCreateDatabase(unencryptedDatabase, "", null);
3839

39-
// NOTE: database not expected to be null, but check:
40+
// NOTE: database not expected to be null, but double-check:
4041
if (database == null) {
4142
Log.e(TAG, "ERROR: got null database object");
4243
return false;
4344
}
4445

45-
database.close();
46+
// *Should* have been recovered:
47+
Cursor cursor = database.rawQuery("select * from sqlite_master;", null);
48+
49+
if (cursor == null) {
50+
Log.e(TAG, "NOT EXPECTED: database.rawQuery() returned null cursor");
51+
return false;
52+
}
53+
54+
// *Should* corrupt the database file that is already open:
55+
ZeteticApplication.getInstance().extractAssetToDatabaseDirectory("corrupt.db");
56+
57+
try {
58+
// Attempt to write to corrupt database file *should* fail:
59+
database.execSQL("CREATE TABLE t1(a,b);");
60+
61+
// NOT EXPECTED to get here:
62+
Log.e(TAG, "NOT EXPECTED: CREATE TABLE succeeded ");
63+
return false;
64+
} catch (SQLiteDatabaseCorruptException ex) {
65+
Log.v(TAG, "Caught SQLiteDatabaseCorruptException as expected OK");
66+
}
67+
68+
// *Expected* to be closed now
69+
if (database.isOpen()) {
70+
Log.e(TAG, "NOT EXPECTED: database is still open");
71+
return false;
72+
}
4673

4774
return true;
4875
} catch (Exception ex) {

0 commit comments

Comments
 (0)