mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 14:45:29 +00:00
0171844651
--HG-- rename : mobile/android/base/db/BrowserContract.java.in => mobile/android/base/db/BrowserContract.java rename : mobile/android/base/db/BrowserProvider.java.in => mobile/android/base/db/BrowserProvider.java rename : mobile/android/base/db/FormHistoryProvider.java.in => mobile/android/base/db/FormHistoryProvider.java rename : mobile/android/base/db/GeckoProvider.java.in => mobile/android/base/db/GeckoProvider.java rename : mobile/android/base/db/PasswordsProvider.java.in => mobile/android/base/db/PasswordsProvider.java rename : mobile/android/base/db/TabsProvider.java.in => mobile/android/base/db/TabsProvider.java
352 lines
13 KiB
Java
352 lines
13 KiB
Java
#filter substitution
|
|
package @ANDROID_PACKAGE_NAME@.tests;
|
|
|
|
import android.content.ContentResolver;
|
|
import android.content.res.AssetManager;
|
|
import android.database.Cursor;
|
|
import android.content.Context;
|
|
import android.net.Uri;
|
|
import android.util.Log;
|
|
import java.io.BufferedInputStream;
|
|
import java.io.File;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.lang.reflect.Method;
|
|
import java.lang.reflect.Constructor;
|
|
import java.util.zip.ZipEntry;
|
|
import java.util.zip.ZipInputStream;
|
|
|
|
/**
|
|
* Tests the profile migration. Unpacks an old database, moves
|
|
* it to the profile, then call the BrowserProvider Control URI
|
|
* to launch a migration and check the results.
|
|
*/
|
|
public class testMigration extends ContentProviderTest {
|
|
// Big files are zipped to allow us to manually extract them,
|
|
// the APK extractor will fail >1Mb.
|
|
private static final String ASSET_SUFFIX = ".zip";
|
|
private static final String DB_NAME = "places.sqlite";
|
|
|
|
@Override
|
|
protected int getTestType() {
|
|
return TEST_MOCHITEST;
|
|
}
|
|
|
|
private File extractAsset(String dbName) {
|
|
File oldDbLocation = null;
|
|
boolean foundFile = false;
|
|
String fullAssetName = dbName + ASSET_SUFFIX;
|
|
|
|
AssetManager assets = getAssetManager();
|
|
try {
|
|
String[] assetList = assets.list("");
|
|
String assetString = "";
|
|
for (String file: assetList) {
|
|
assetString = assetString.concat(file);
|
|
assetString = assetString.concat(" ");
|
|
if (file.equals(fullAssetName)) {
|
|
foundFile = true;
|
|
}
|
|
}
|
|
mAsserter.is(foundFile, true, fullAssetName + " found in assets: " + assetString);
|
|
} catch (IOException e) {
|
|
String stackTrace = Log.getStackTraceString(e);
|
|
mAsserter.is(false, true, "Error getting asset dir: " + stackTrace);
|
|
}
|
|
|
|
// Extract the old places database from assets
|
|
// and write it out in the profile directory
|
|
try {
|
|
InputStream profData = assets.open(fullAssetName);
|
|
File profile = new File(mProfile);
|
|
oldDbLocation = new File(profile, dbName);
|
|
OutputStream out = new FileOutputStream(oldDbLocation);
|
|
|
|
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(profData));
|
|
try {
|
|
ZipEntry ze;
|
|
while ((ze = zis.getNextEntry()) != null) {
|
|
byte[] buffer = new byte[1024];
|
|
int count;
|
|
while ((count = zis.read(buffer)) != -1) {
|
|
out.write(buffer, 0, count);
|
|
}
|
|
String fileName = ze.getName();
|
|
mAsserter.is(fileName, DB_NAME, "Filename match: " + fileName);
|
|
}
|
|
} finally {
|
|
zis.close();
|
|
}
|
|
|
|
profData.close();
|
|
out.flush();
|
|
out.close();
|
|
} catch (IOException e) {
|
|
String stackTrace = Log.getStackTraceString(e);
|
|
mAsserter.is(false, true, "Error getting profile data: " + stackTrace);
|
|
}
|
|
|
|
return oldDbLocation;
|
|
}
|
|
|
|
public void testMigration() {
|
|
Context context = (Context)getActivity();
|
|
|
|
File oldDbLocation = extractAsset(DB_NAME);
|
|
mAsserter.is(oldDbLocation.exists(), true, "OK old file exists: "
|
|
+ oldDbLocation.toString());
|
|
|
|
// Set up BrowserDB
|
|
try {
|
|
Class browserDBClass =
|
|
mClassLoader.loadClass("org.mozilla.gecko.db.BrowserDB");
|
|
Method initializeMethod =
|
|
browserDBClass.getDeclaredMethod("initialize", String.class);
|
|
initializeMethod.invoke(null, "default");
|
|
} catch (Exception ex) {
|
|
mAsserter.is(true, false, "Error setting up BrowserDB: "
|
|
+ ex.getMessage());
|
|
return;
|
|
}
|
|
|
|
// Use reflection to look up the ProfileMigrator things we need
|
|
// access to (constructor, launch), as well as BrowserContract.Control.
|
|
Method launchPlacesTest;
|
|
Constructor constructor;
|
|
Class pmClass;
|
|
|
|
try {
|
|
pmClass = mClassLoader.loadClass("org.mozilla.gecko.ProfileMigrator");
|
|
launchPlacesTest = pmClass.getMethod("launchPlacesTest", File.class);
|
|
constructor = pmClass.getConstructor(Context.class, ContentResolver.class);
|
|
} catch(ClassNotFoundException ex) {
|
|
mAsserter.is(false, true, "Error getting class: " + ex.getMessage());
|
|
return;
|
|
} catch (java.lang.NoSuchMethodException ex) {
|
|
mAsserter.is(true, false, "Unable to find method: " + ex.getMessage());
|
|
return;
|
|
}
|
|
|
|
Object pm = null;
|
|
try {
|
|
// Construct ProfileMigrator object
|
|
pm = constructor.newInstance(context, mResolver);
|
|
} catch (Exception ex) {
|
|
mAsserter.is(true, false, "Error instantiating ProfileMigrator instance: "
|
|
+ ex.getMessage());
|
|
return;
|
|
}
|
|
|
|
// Reset history entries from previous tests
|
|
clearHistory();
|
|
|
|
// Launch the Profile Migration
|
|
try {
|
|
launchPlacesTest.invoke(pm, new File(mProfile));
|
|
} catch (Exception ex) {
|
|
String stackTrace = Log.getStackTraceString(ex);
|
|
mAsserter.is(true, false, "Unable to invoke launchPlacesTest:" + stackTrace);
|
|
return;
|
|
}
|
|
|
|
// Run the tests to see if that worked
|
|
runTestViaContentProvider();
|
|
runTestViaBrowserDB();
|
|
|
|
mAsserter.is(oldDbLocation.exists(), false, "OK old file gone now");
|
|
}
|
|
|
|
private void clearHistory() {
|
|
Method clearHistory = null;
|
|
|
|
try {
|
|
Class browserDB =
|
|
mClassLoader.loadClass("org.mozilla.gecko.db.BrowserDB");
|
|
clearHistory =
|
|
browserDB.getMethod("clearHistory", ContentResolver.class);
|
|
} catch (java.lang.ClassNotFoundException ex) {
|
|
mAsserter.is(true, false, "Unable to find class");
|
|
return;
|
|
} catch (java.lang.NoSuchMethodException ex) {
|
|
mAsserter.is(true, false, "Unable to find method");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
clearHistory.invoke(null, mResolver);
|
|
} catch (Exception ex) {
|
|
String stackTrace = Log.getStackTraceString(ex);
|
|
mAsserter.is(true, false, "Exception clearing history:" + stackTrace);
|
|
}
|
|
}
|
|
|
|
// stolen from testBookmarks
|
|
private void runTestViaBrowserDB() {
|
|
Method isBookmarked = null;
|
|
Method getAllVisitedHistory = null;
|
|
Constructor constructor = null;
|
|
|
|
try {
|
|
Class localBrowserDB =
|
|
mClassLoader.loadClass("org.mozilla.gecko.db.LocalBrowserDB");
|
|
isBookmarked =
|
|
localBrowserDB.getMethod("isBookmark", ContentResolver.class, String.class);
|
|
getAllVisitedHistory =
|
|
localBrowserDB.getMethod("getAllVisitedHistory", ContentResolver.class);
|
|
constructor = localBrowserDB.getConstructor(String.class);
|
|
} catch (java.lang.ClassNotFoundException ex) {
|
|
mAsserter.is(true, false, "Unable to find class");
|
|
return;
|
|
} catch (java.lang.NoSuchMethodException ex) {
|
|
mAsserter.is(true, false, "Unable to find method:" + ex.getMessage());
|
|
return;
|
|
}
|
|
|
|
Object db = null;
|
|
try {
|
|
String defaultProfile = "default";
|
|
db = constructor.newInstance(defaultProfile);
|
|
} catch (Exception ex) {
|
|
mAsserter.is(true, false, "Error instantiating LocalBrowserDB instance: "
|
|
+ ex.getMessage());
|
|
return;
|
|
}
|
|
|
|
final String[] knownBookmarks = new String[] {
|
|
"http://www.androidpolice.com/",
|
|
"https://developer.mozilla.org/En/Mozilla_Coding_Style_Guide",
|
|
"http://planet.mozilla.org/",
|
|
"http://www.crockford.com/",
|
|
"https://wiki.mozilla.org/Mobile/Fennec/Android"
|
|
};
|
|
final String ABOUT_HOME_URL = "about:home";
|
|
|
|
for (String url: knownBookmarks) {
|
|
try {
|
|
// Check for some bookmarks we know must exist
|
|
boolean isbookmark =
|
|
(Boolean)isBookmarked.invoke(db,
|
|
mResolver,
|
|
url);
|
|
mAsserter.is(isbookmark, true, "Expected page is bookmarked: " + url);
|
|
} catch (Exception ex) {
|
|
mAsserter.is(true, false, "Exception checking bookmark existence");
|
|
ex.printStackTrace();
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Check the amount of history, this should match the following on the
|
|
// database in assets:
|
|
// SELECT COUNT(DISTINCT(url)) FROM moz_historyvisits
|
|
// JOIN moz_places ON moz_historyvisits.place_id = moz_places.id
|
|
final int PLACES_KNOWN_HISTORY_URLS = 184;
|
|
try {
|
|
Cursor cursor =
|
|
(Cursor)getAllVisitedHistory.invoke(db,
|
|
mResolver);
|
|
int historyCount = cursor.getCount();
|
|
cursor.close();
|
|
mAsserter.is(historyCount, PLACES_KNOWN_HISTORY_URLS,
|
|
"History count " + historyCount +
|
|
", expected was " + PLACES_KNOWN_HISTORY_URLS);
|
|
} catch (Exception ex) {
|
|
mAsserter.is(true, false, "Exception checking history count");
|
|
ex.printStackTrace();
|
|
}
|
|
}
|
|
|
|
private void runTestViaContentProvider() {
|
|
String ensureHistory;
|
|
String ensureBookmarks;
|
|
String urlField;
|
|
String visitsField;
|
|
|
|
Uri controlUri;
|
|
Uri historyUri;
|
|
|
|
try {
|
|
Class browserContract =
|
|
mClassLoader.loadClass("org.mozilla.gecko.db.BrowserContract");
|
|
Class browserContractControl =
|
|
mClassLoader.loadClass("org.mozilla.gecko.db.BrowserContract$Control");
|
|
Class browserContractHistory =
|
|
mClassLoader.loadClass("org.mozilla.gecko.db.BrowserContract$History");
|
|
Class browserContractUrl =
|
|
mClassLoader.loadClass("org.mozilla.gecko.db.BrowserContract$URLColumns");
|
|
Class browserContractHistoryColumns =
|
|
mClassLoader.loadClass("org.mozilla.gecko.db.BrowserContract$HistoryColumns");
|
|
|
|
controlUri = (Uri)browserContractControl.getField("CONTENT_URI").get(null);
|
|
historyUri = (Uri)browserContractHistory.getField("CONTENT_URI").get(null);
|
|
urlField = (String)browserContractUrl.getField("URL").get(null);
|
|
visitsField = (String)browserContractHistoryColumns.getField("VISITS").get(null);
|
|
String profilePath = (String)browserContract.getField("PARAM_PROFILE_PATH").get(null);
|
|
Uri.Builder builder = controlUri.buildUpon();
|
|
controlUri = builder.build();
|
|
ensureHistory =
|
|
(String)browserContractControl.getField("ENSURE_HISTORY_MIGRATED").get(null);
|
|
ensureBookmarks =
|
|
(String)browserContractControl.getField("ENSURE_BOOKMARKS_MIGRATED").get(null);
|
|
} catch (Exception ex) {
|
|
mAsserter.is(true, false, "Reflection error getting BrowserContract classes and Uri's");
|
|
ex.printStackTrace();
|
|
return;
|
|
}
|
|
|
|
Cursor c = mResolver.query(controlUri,
|
|
new String[] { ensureHistory,
|
|
ensureBookmarks },
|
|
null,
|
|
null,
|
|
null);
|
|
|
|
int historyMigrated = 0;
|
|
int bookmarksMigrated = 0;
|
|
|
|
if (c.moveToFirst()) {
|
|
historyMigrated = c.getInt(0);
|
|
bookmarksMigrated = c.getInt(1);
|
|
}
|
|
c.close();
|
|
|
|
mAsserter.is(historyMigrated, 1, "History migrated");
|
|
mAsserter.is(bookmarksMigrated, 1, "Bookmarks migrated");
|
|
|
|
// Check whether visit counts are as expected. The test profile
|
|
// has visited reddit 4 times so we expect to find that in our
|
|
// own database too now.
|
|
c = mResolver.query(historyUri,
|
|
new String[] { visitsField },
|
|
urlField + " = ?",
|
|
new String[] { "http://www.reddit.com/" },
|
|
null);
|
|
mAsserter.is(c.moveToFirst(), true, "Expected URL found");
|
|
int visits = c.getInt(0);
|
|
c.close();
|
|
|
|
mAsserter.is(visits, 4, "Visit count of " + visits + " equals expected 4");
|
|
}
|
|
|
|
@Override
|
|
public void setUp() throws Exception {
|
|
super.setUp("org.mozilla.gecko.db.BrowserProvider", "AUTHORITY");
|
|
}
|
|
|
|
@Override
|
|
public void tearDown() throws Exception {
|
|
// remove the database file
|
|
File profile = new File(mProfile);
|
|
File db = new File(profile, DB_NAME);
|
|
if (db.delete()) {
|
|
mAsserter.dumpLog("tearDown deleted "+db.toString());
|
|
} else {
|
|
mAsserter.dumpLog("tearDown did not delete "+db.toString());
|
|
}
|
|
|
|
super.tearDown();
|
|
}
|
|
}
|