Fix LocalStoreUnitTests

The problem was that we tried to upgrade the db by re-creating a LocalStore,
without closing the existing connection.  The db was still upgraded on the
filesystem, but the old connection kept looking at the old table definition
for whatever reason.

Also cleaned up checkAllTablesFound().  It now shows what columns are
missing when failed.

Bug 3349973

Change-Id: I80f4c67f1bd61cd5e1f12a632978b36a6e0a3b19
This commit is contained in:
Makoto Onuki 2011-01-14 14:32:52 -08:00
parent 36cc9c18ed
commit 36f2088408
1 changed files with 99 additions and 96 deletions

View File

@ -40,12 +40,11 @@ import android.content.ContentValues;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.test.AndroidTestCase; import android.test.AndroidTestCase;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.MediumTest;
import java.io.File; import java.io.File;
import java.net.URI; import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
/** /**
@ -141,20 +140,23 @@ public class LocalStoreUnitTests extends AndroidTestCase {
mDatabase = SQLiteDatabase.openOrCreateDatabase(new URI(mLocalStoreUri).getPath(), null); mDatabase = SQLiteDatabase.openOrCreateDatabase(new URI(mLocalStoreUri).getPath(), null);
} }
private void closeDatabase() { private boolean closeDatabase() {
if (mDatabase != null) { if (mDatabase != null) {
mDatabase.close(); mDatabase.close();
mDatabase = null; mDatabase = null;
return true;
} }
return false;
} }
/** /**
* Create a new {@link LocalStore} instance and close it. * Upgrades the database.
*
* It'll upgrade the existing database.
*/ */
private void createAndCloseLocalStore() throws Exception { private void upgradeDatabase() throws Exception {
// Need to close the db if it's already open.
boolean opened = closeDatabase();
LocalStore.newInstance(mLocalStoreUri, getContext(), null).close(); LocalStore.newInstance(mLocalStoreUri, getContext(), null).close();
if (opened) openDatabase();
} }
/** /**
@ -987,7 +989,7 @@ public class LocalStoreUnitTests extends AndroidTestCase {
*/ */
public void testDbVersion() throws Exception { public void testDbVersion() throws Exception {
// build current version database. // build current version database.
createAndCloseLocalStore(); upgradeDatabase();
openDatabase(); openDatabase();
@ -1057,7 +1059,7 @@ public class LocalStoreUnitTests extends AndroidTestCase {
expectedAttachment.put("id", mDatabase.insert("attachments", null, initialAttachment)); expectedAttachment.put("id", mDatabase.insert("attachments", null, initialAttachment));
// upgrade database 18 to latest // upgrade database 18 to latest
createAndCloseLocalStore(); upgradeDatabase();
// added message_id column should be initialized as null // added message_id column should be initialized as null
expectedMessage.put("message_id", (String) null); // message_id type text == String expectedMessage.put("message_id", (String) null); // message_id type text == String
@ -1125,7 +1127,7 @@ public class LocalStoreUnitTests extends AndroidTestCase {
expectedAttachment.put("id", mDatabase.insert("attachments", null, initialAttachment)); expectedAttachment.put("id", mDatabase.insert("attachments", null, initialAttachment));
// upgrade database 19 to latest // upgrade database 19 to latest
createAndCloseLocalStore(); upgradeDatabase();
// added content_id column should be initialized as null // added content_id column should be initialized as null
expectedAttachment.put("content_id", (String) null); // content_id type text == String expectedAttachment.put("content_id", (String) null); // content_id type text == String
@ -1141,30 +1143,36 @@ public class LocalStoreUnitTests extends AndroidTestCase {
c = mDatabase.query("messages", c = mDatabase.query("messages",
new String[] { "id", "folder_id", "internal_date", "message_id" }, new String[] { "id", "folder_id", "internal_date", "message_id" },
null, null, null, null, null); null, null, null, null, null);
// check if data is available try {
assertTrue("attachments table should have one data", c.moveToNext()); // check if data is available
assertTrue("attachments table should have one data", c.moveToNext());
// check if data are expected // check if data are expected
final ContentValues actualMessage = cursorToContentValues(c, final ContentValues actualMessage = cursorToContentValues(c,
new String[] { "primary", "integer", "integer", "text" }); new String[] { "primary", "integer", "integer", "text" });
assertEquals("messages table cursor does not have expected values", assertEquals("messages table cursor does not have expected values",
expectedMessage, actualMessage); expectedMessage, actualMessage);
c.close(); } finally {
c.close();
}
// check attachment table // check attachment table
c = mDatabase.query("attachments", c = mDatabase.query("attachments",
new String[] { "id", "message_id", "mime_type", "content_id" }, new String[] { "id", "message_id", "mime_type", "content_id" },
null, null, null, null, null); null, null, null, null, null);
// check if data is available try {
assertTrue("attachments table should have one data", c.moveToNext()); // check if data is available
assertTrue("attachments table should have one data", c.moveToNext());
// check if data are expected // check if data are expected
final ContentValues actualAttachment = cursorToContentValues(c, final ContentValues actualAttachment = cursorToContentValues(c,
new String[] { "primary", "integer", "text", "text" }); new String[] { "primary", "integer", "text", "text" });
assertEquals("attachment table cursor does not have expected values", assertEquals("attachment table cursor does not have expected values",
expectedAttachment, actualAttachment); expectedAttachment, actualAttachment);
c.close(); } finally {
c.close();
}
} }
/** /**
@ -1177,7 +1185,7 @@ public class LocalStoreUnitTests extends AndroidTestCase {
createSampleDb(mDatabase, 20); createSampleDb(mDatabase, 20);
// upgrade database 20 to latest // upgrade database 20 to latest
createAndCloseLocalStore(); upgradeDatabase();
// database should be upgraded // database should be upgraded
assertEquals("database should be upgraded", DATABASE_VERSION, mDatabase.getVersion()); assertEquals("database should be upgraded", DATABASE_VERSION, mDatabase.getVersion());
@ -1196,7 +1204,7 @@ public class LocalStoreUnitTests extends AndroidTestCase {
createSampleDb(mDatabase, 21); createSampleDb(mDatabase, 21);
// upgrade database 21 to latest // upgrade database 21 to latest
createAndCloseLocalStore(); upgradeDatabase();
// database should be upgraded // database should be upgraded
assertEquals("database should be upgraded", DATABASE_VERSION, mDatabase.getVersion()); assertEquals("database should be upgraded", DATABASE_VERSION, mDatabase.getVersion());
@ -1235,7 +1243,7 @@ public class LocalStoreUnitTests extends AndroidTestCase {
outMessage3.put("id", mDatabase.insert("messages", null, inMessage3)); outMessage3.put("id", mDatabase.insert("messages", null, inMessage3));
// upgrade database 22 to latest // upgrade database 22 to latest
createAndCloseLocalStore(); upgradeDatabase();
// database should be upgraded // database should be upgraded
assertEquals("database should be upgraded", DATABASE_VERSION, mDatabase.getVersion()); assertEquals("database should be upgraded", DATABASE_VERSION, mDatabase.getVersion());
@ -1247,27 +1255,29 @@ public class LocalStoreUnitTests extends AndroidTestCase {
String[] columns = new String[] { "id", "message_id", "flags", String[] columns = new String[] { "id", "message_id", "flags",
"flag_downloaded_full", "flag_downloaded_partial", "flag_deleted" }; "flag_downloaded_full", "flag_downloaded_partial", "flag_deleted" };
Cursor c = mDatabase.query("messages", columns, null, null, null, null, null); Cursor c = mDatabase.query("messages", columns, null, null, null, null, null);
try {
for (int msgNum = 0; msgNum <= 2; ++msgNum) { for (int msgNum = 0; msgNum <= 2; ++msgNum) {
assertTrue(c.moveToNext()); assertTrue(c.moveToNext());
ContentValues actualMessage = cursorToContentValues(c, ContentValues actualMessage = cursorToContentValues(c, new String[] {
new String[] { "primary", "text", "text", "integer", "integer", "integer" }); "primary", "text", "text", "integer", "integer", "integer" });
String messageId = actualMessage.getAsString("message_id"); String messageId = actualMessage.getAsString("message_id");
int outDlFull = actualMessage.getAsInteger("flag_downloaded_full"); int outDlFull = actualMessage.getAsInteger("flag_downloaded_full");
int outDlPartial = actualMessage.getAsInteger("flag_downloaded_partial"); int outDlPartial = actualMessage.getAsInteger("flag_downloaded_partial");
int outDeleted = actualMessage.getAsInteger("flag_deleted"); int outDeleted = actualMessage.getAsInteger("flag_deleted");
if ("x".equals(messageId)) { if ("x".equals(messageId)) {
assertTrue("converted flag_downloaded_full", assertTrue("converted flag_downloaded_full",
outDlFull == 1 && outDlPartial == 0 && outDeleted == 0); outDlFull == 1 && outDlPartial == 0 && outDeleted == 0);
} else if ("y".equals(messageId)) { } else if ("y".equals(messageId)) {
assertTrue("converted flag_downloaded_partial", assertTrue("converted flag_downloaded_partial",
outDlFull == 0 && outDlPartial == 1 && outDeleted == 0); outDlFull == 0 && outDlPartial == 1 && outDeleted == 0);
} else if ("z".equals(messageId)) { } else if ("z".equals(messageId)) {
assertTrue("converted flag_deleted", assertTrue("converted flag_deleted",
outDlFull == 0 && outDlPartial == 0 && outDeleted == 1); outDlFull == 0 && outDlPartial == 0 && outDeleted == 1);
}
} }
} finally {
c.close();
} }
c.close();
} }
/** /**
@ -1287,7 +1297,7 @@ public class LocalStoreUnitTests extends AndroidTestCase {
expectedMessage.put("id", mDatabase.insert("messages", null, initialMessage)); expectedMessage.put("id", mDatabase.insert("messages", null, initialMessage));
// upgrade database 23 to latest // upgrade database 23 to latest
createAndCloseLocalStore(); upgradeDatabase();
// added message_id column should be initialized as null // added message_id column should be initialized as null
expectedMessage.put("message_id", (String) null); // message_id type text == String expectedMessage.put("message_id", (String) null); // message_id type text == String
@ -1303,63 +1313,56 @@ public class LocalStoreUnitTests extends AndroidTestCase {
c = mDatabase.query("messages", c = mDatabase.query("messages",
new String[] { "id", "folder_id", "internal_date", "message_id" }, new String[] { "id", "folder_id", "internal_date", "message_id" },
null, null, null, null, null); null, null, null, null, null);
// check if data is available try {
assertTrue("messages table should have one data", c.moveToNext()); // check if data is available
assertTrue("messages table should have one data", c.moveToNext());
// check if data are expected // check if data are expected
final ContentValues actualMessage = cursorToContentValues(c, final ContentValues actualMessage = cursorToContentValues(c,
new String[] { "primary", "integer", "integer", "text" }); new String[] { "primary", "integer", "integer", "text" });
assertEquals("messages table cursor does not have expected values", assertEquals("messages table cursor does not have expected values",
expectedMessage, actualMessage); expectedMessage, actualMessage);
c.close(); } finally {
c.close();
}
} }
/** /**
* Checks the database to confirm that all tables, with all expected columns are found. * Checks the database to confirm that all tables, with all expected columns are found.
*/ */
private void checkAllTablesFound(SQLiteDatabase db) { private void checkAllTablesFound(SQLiteDatabase db) {
Cursor c; checkColumnNames(db, "messages",
HashSet<String> foundNames; "id", "folder_id", "uid", "subject", "date", "flags", "sender_list",
ArrayList<String> expectedNames; "to_list", "cc_list", "bcc_list", "reply_to_list",
"html_content", "text_content", "attachment_count",
"internal_date", "store_flag_1", "store_flag_2", "flag_downloaded_full",
"flag_downloaded_partial", "flag_deleted", "x_headers"
);
checkColumnNames(db, "attachments",
"id", "message_id",
"store_data", "content_uri", "size", "name",
"mime_type", "content_id"
);
checkColumnNames(db, "remote_store_data",
"id", "folder_id", "data_key", "data"
);
}
// check for up-to-date messages table private void checkColumnNames(SQLiteDatabase db, String tableName, String... expectedColumns) {
c = db.query("messages", Cursor c = db.query(tableName, null, null, null, null, null, null);
null, try {
null, null, null, null, null); final HashSet<String> expectedSet = new HashSet<String>();
foundNames = cursorToColumnNames(c); for (String expectedColumn : expectedColumns) {
expectedNames = new ArrayList<String>(Arrays.asList( expectedSet.add(expectedColumn);
new String[]{ "id", "folder_id", "uid", "subject", "date", "flags", "sender_list", }
"to_list", "cc_list", "bcc_list", "reply_to_list", final HashSet<String> actualSet = cursorToColumnNames(c);
"html_content", "text_content", "attachment_count",
"internal_date", "store_flag_1", "store_flag_2", "flag_downloaded_full",
"flag_downloaded_partial", "flag_deleted", "x_headers" }
));
assertTrue("messages", foundNames.containsAll(expectedNames));
c.close();
// check for up-to-date attachments table expectedSet.removeAll(actualSet);
c = db.query("attachments",
null,
null, null, null, null, null);
foundNames = cursorToColumnNames(c);
expectedNames = new ArrayList<String>(Arrays.asList(
new String[]{ "id", "message_id",
"store_data", "content_uri", "size", "name",
"mime_type", "content_id" }
));
assertTrue("attachments", foundNames.containsAll(expectedNames));
c.close();
// check for up-to-date remote_store_data table MoreAsserts.assertEmpty(expectedSet);
c = db.query("remote_store_data", } finally {
null, c.close();
null, null, null, null, null); }
foundNames = cursorToColumnNames(c);
expectedNames = new ArrayList<String>(Arrays.asList(
new String[]{ "id", "folder_id", "data_key", "data" }
));
assertTrue("remote_store_data", foundNames.containsAll(expectedNames));
c.close();
} }
private static void createSampleDb(SQLiteDatabase db, int version) { private static void createSampleDb(SQLiteDatabase db, int version) {