Bug 834543 - Part 1: Async helpers and unit tests. r=mak

This commit is contained in:
Raymond Lee 2013-03-22 01:06:15 +08:00
parent a68cc5ff41
commit 2a224d8994
5 changed files with 206 additions and 138 deletions

View File

@ -32,15 +32,17 @@ const Cu = Components.utils;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyGetter(this, "Services", function() {
Cu.import("resource://gre/modules/Services.jsm");
return Services;
});
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyGetter(this, "NetUtil", function() {
Cu.import("resource://gre/modules/NetUtil.jsm");
return NetUtil;
});
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
"resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task",
"resource://gre/modules/Task.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Promise",
"resource://gre/modules/commonjs/sdk/core/promise.js");
// The minimum amount of transactions before starting a batch. Usually we do
// do incremental updates, a batch will cause views to completely
@ -90,6 +92,7 @@ this.PlacesUtils = {
LMANNO_SITEURI: "livemark/siteURI",
POST_DATA_ANNO: "bookmarkProperties/POSTData",
READ_ONLY_ANNO: "placesInternal/READ_ONLY",
CHARSET_ANNO: "URIProperties/characterSet",
TOPIC_SHUTDOWN: "places-shutdown",
TOPIC_INIT_COMPLETE: "places-init-complete",
@ -2076,6 +2079,63 @@ this.PlacesUtils = {
if (index != -1) {
this._bookmarksServiceObserversQueue.splice(index, 1);
}
},
/**
* Sets the character-set for a URI.
*
* @param aURI nsIURI
* @param aCharset character-set value.
* @return {Promise}
*/
setCharsetForURI: function PU_setCharsetForURI(aURI, aCharset) {
let deferred = Promise.defer();
// Delaying to catch issues with asynchronous behavior while waiting
// to implement asynchronous annotations in bug 699844.
Services.tm.mainThread.dispatch(function() {
if (aCharset && aCharset.length > 0) {
PlacesUtils.annotations.setPageAnnotation(
aURI, PlacesUtils.CHARSET_ANNO, aCharset, 0,
Ci.nsIAnnotationService.EXPIRE_NEVER);
} else {
PlacesUtils.annotations.removePageAnnotation(
aURI, PlacesUtils.CHARSET_ANNO);
}
deferred.resolve();
}, Ci.nsIThread.DISPATCH_NORMAL);
return deferred.promise;
},
/**
* Gets the last saved character-set for a URI.
*
* @param aURI nsIURI
* @param [optional] aCallback
* the callback method that reruns a character-set or null.
* @return {Promise}
* @resolve a character-set or null.
*/
getCharsetForURI: function PU_getCharsetForURI(aURI, aCallback) {
let deferred = Promise.defer();
Services.tm.mainThread.dispatch(function() {
let charset = null;
try {
charset = PlacesUtils.annotations.getPageAnnotation(aURI,
PlacesUtils.CHARSET_ANNO);
} catch (ex) { }
if (aCallback) {
aCallback(charset);
}
deferred.resolve(charset);
}, Ci.nsIThread.DISPATCH_NORMAL);
return deferred.promise;
}
};

View File

@ -7,19 +7,6 @@
const charset = "UTF-8";
const CHARSET_ANNO = "URIProperties/characterSet";
// Get history service
try {
var histsvc = Cc["@mozilla.org/browser/nav-history-service;1"].
getService(Ci.nsINavHistoryService);
var bhist = histsvc.QueryInterface(Ci.nsIBrowserHistory);
var bmsvc = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
getService(Ci.nsINavBookmarksService);
var annosvc = Cc["@mozilla.org/browser/annotation-service;1"].
getService(Ci.nsIAnnotationService);
} catch(ex) {
do_throw("Could not get services\n");
}
const TEST_URI = uri("http://foo.com");
const TEST_BOOKMARKED_URI = uri("http://bar.com");
@ -35,41 +22,44 @@ add_task(function test_execute()
yield promiseAddVisits(TEST_BOOKMARKED_URI);
// create bookmarks on TEST_BOOKMARKED_URI
var bm1 = bmsvc.insertBookmark(bmsvc.unfiledBookmarksFolder,
TEST_BOOKMARKED_URI, bmsvc.DEFAULT_INDEX,
TEST_BOOKMARKED_URI.spec);
var bm2 = bmsvc.insertBookmark(bmsvc.toolbarFolder,
TEST_BOOKMARKED_URI, bmsvc.DEFAULT_INDEX,
TEST_BOOKMARKED_URI.spec);
var bm1 = PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.unfiledBookmarksFolderId,
TEST_BOOKMARKED_URI, PlacesUtils.bookmarks.DEFAULT_INDEX,
TEST_BOOKMARKED_URI.spec);
var bm2 = PlacesUtils.bookmarks.insertBookmark(
PlacesUtils.toolbarFolderId,
TEST_BOOKMARKED_URI, PlacesUtils.bookmarks.DEFAULT_INDEX,
TEST_BOOKMARKED_URI.spec);
// set charset on not-bookmarked page
histsvc.setCharsetForURI(TEST_URI, charset);
yield PlacesUtils.setCharsetForURI(TEST_URI, charset);
// set charset on bookmarked page
histsvc.setCharsetForURI(TEST_BOOKMARKED_URI, charset);
yield PlacesUtils.setCharsetForURI(TEST_BOOKMARKED_URI, charset);
// check that we have created a page annotation
do_check_eq(annosvc.getPageAnnotation(TEST_URI, CHARSET_ANNO), charset);
do_check_eq(PlacesUtils.annotations.getPageAnnotation(TEST_URI, CHARSET_ANNO), charset);
// get charset from not-bookmarked page
do_check_eq(histsvc.getCharsetForURI(TEST_URI), charset);
do_check_eq((yield PlacesUtils.getCharsetForURI(TEST_URI)), charset);
// get charset from bookmarked page
do_check_eq(histsvc.getCharsetForURI(TEST_BOOKMARKED_URI), charset);
do_check_eq((yield PlacesUtils.getCharsetForURI(TEST_BOOKMARKED_URI)), charset);
yield promiseClearHistory();
// ensure that charset has gone for not-bookmarked page
do_check_neq(histsvc.getCharsetForURI(TEST_URI), charset);
do_check_neq((yield PlacesUtils.getCharsetForURI(TEST_URI)), charset);
// check that page annotation has been removed
try {
annosvc.getPageAnnotation(TEST_URI, CHARSET_ANNO);
PlacesUtils.annotations.getPageAnnotation(TEST_URI, CHARSET_ANNO);
do_throw("Charset page annotation has not been removed correctly");
} catch (e) {}
// ensure that charset still exists for bookmarked page
do_check_eq(histsvc.getCharsetForURI(TEST_BOOKMARKED_URI), charset);
do_check_eq((yield PlacesUtils.getCharsetForURI(TEST_BOOKMARKED_URI)), charset);
// remove charset from bookmark and check that has gone
histsvc.setCharsetForURI(TEST_BOOKMARKED_URI, "");
do_check_neq(histsvc.getCharsetForURI(TEST_BOOKMARKED_URI), charset);
yield PlacesUtils.setCharsetForURI(TEST_BOOKMARKED_URI, "");
do_check_neq((yield PlacesUtils.getCharsetForURI(TEST_BOOKMARKED_URI)), charset);
});

View File

@ -55,9 +55,10 @@ function run_test() {
populate();
// 2. run the test-suite
validate();
Task.spawn(function() {
yield validate();
yield promiseAsyncUpdates();
promiseAsyncUpdates().then(function testJsonExport() {
// Test exporting a Places canonical json file.
// 1. export to bookmarks.exported.json
try {
@ -73,10 +74,11 @@ function run_test() {
LOG("imported json");
// 4. run the test-suite
validate();
yield validate();
LOG("validated import");
promiseAsyncUpdates().then(do_test_finished);
yield promiseAsyncUpdates();
do_test_finished();
});
}
}
@ -114,7 +116,7 @@ function populate() {
}
function validate() {
testCanonicalBookmarks(PlacesUtils.bookmarks.bookmarksMenuFolder);
yield testCanonicalBookmarks();
testToolbarFolder();
testUnfiledBookmarks();
testTags();
@ -125,7 +127,7 @@ function validate() {
function testCanonicalBookmarks() {
// query to see if the deleted folder and items have been imported
var query = PlacesUtils.history.getNewQuery();
query.setFolders([PlacesUtils.bookmarks.bookmarksMenuFolder], 1);
query.setFolders([PlacesUtils.bookmarksMenuFolderId], 1);
var result = PlacesUtils.history.executeQuery(query, PlacesUtils.history.getNewQueryOptions());
var rootNode = result.root;
rootNode.containerOpen = true;
@ -189,7 +191,7 @@ function testCanonicalBookmarks() {
// last charset
var testURI = PlacesUtils._uri(testBookmark1.uri);
do_check_eq("ISO-8859-1", PlacesUtils.history.getCharsetForURI(testURI));
do_check_eq("ISO-8859-1", (yield PlacesUtils.getCharsetForURI(testURI)));
// description
do_check_true(PlacesUtils.annotations.itemHasAnnotation(testBookmark1.itemId,
@ -205,7 +207,7 @@ function testCanonicalBookmarks() {
function testToolbarFolder() {
var query = PlacesUtils.history.getNewQuery();
query.setFolders([PlacesUtils.bookmarks.toolbarFolder], 1);
query.setFolders([PlacesUtils.toolbarFolderId], 1);
var result = PlacesUtils.history.executeQuery(query, PlacesUtils.history.getNewQueryOptions());
var toolbar = result.root;
@ -243,7 +245,7 @@ function testToolbarFolder() {
function testUnfiledBookmarks() {
var query = PlacesUtils.history.getNewQuery();
query.setFolders([PlacesUtils.bookmarks.unfiledBookmarksFolder], 1);
query.setFolders([PlacesUtils.unfiledBookmarksFolderId], 1);
var result = PlacesUtils.history.executeQuery(query, PlacesUtils.history.getNewQueryOptions());
var rootNode = result.root;
rootNode.containerOpen = true;

View File

@ -100,7 +100,7 @@ add_task(function setup() {
// Note: we do not empty the db before this import to catch bugs like 380999
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileOld, true);
yield promiseAsyncUpdates();
testImportedBookmarks();
yield testImportedBookmarks();
yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
yield promiseAsyncUpdates();
@ -115,7 +115,7 @@ add_task(function test_import_new()
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
testImportedBookmarks();
yield testImportedBookmarks();
yield promiseAsyncUpdates();
remove_all_bookmarks();
@ -148,7 +148,7 @@ add_task(function test_emptytitle_export()
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
testImportedBookmarks();
yield testImportedBookmarks();
// Cleanup.
test_bookmarks.unfiled.pop();
@ -214,7 +214,7 @@ add_task(function test_import_chromefavicon()
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
testImportedBookmarks();
yield testImportedBookmarks();
// Cleanup.
test_bookmarks.unfiled.pop();
@ -239,7 +239,7 @@ add_task(function test_import_ontop()
yield BookmarkHTMLUtils.exportToFile(gBookmarksFileNew);
yield BookmarkHTMLUtils.importFromFile(gBookmarksFileNew, true);
yield promiseAsyncUpdates();
testImportedBookmarks();
yield testImportedBookmarks();
yield promiseAsyncUpdates();
remove_all_bookmarks();
});
@ -265,7 +265,9 @@ function testImportedBookmarks()
let items = test_bookmarks[group];
do_check_eq(root.childCount, items.length);
items.forEach(function (item, index) checkItem(item, root.getChild(index)));
for (let key in items) {
yield checkItem(items[key], root.getChild(key));
}
root.containerOpen = false;
}
@ -304,87 +306,102 @@ function testImportedBookmarksToFolder(aFolder)
function checkItem(aExpected, aNode)
{
let id = aNode.itemId;
for (prop in aExpected) {
switch (prop) {
case "type":
do_check_eq(aNode.type, aExpected.type);
break;
case "title":
do_check_eq(aNode.title, aExpected.title);
break;
case "description":
do_check_eq(PlacesUtils.annotations
.getItemAnnotation(id, DESCRIPTION_ANNO),
aExpected.description);
break;
case "dateAdded":
let deferred = Promise.defer();
Task.spawn(function() {
for (prop in aExpected) {
switch (prop) {
case "type":
do_check_eq(aNode.type, aExpected.type);
break;
case "title":
do_check_eq(aNode.title, aExpected.title);
break;
case "description":
do_check_eq(PlacesUtils.annotations
.getItemAnnotation(id, DESCRIPTION_ANNO),
aExpected.description);
break;
case "dateAdded":
do_check_eq(PlacesUtils.bookmarks.getItemDateAdded(id),
aExpected.dateAdded);
break;
case "lastModified":
break;
case "lastModified":
do_check_eq(PlacesUtils.bookmarks.getItemLastModified(id),
aExpected.lastModified);
break;
case "url":
PlacesUtils.livemarks.getLivemark(
{ id: id },
function (aStatus, aLivemark) {
if (!Components.isSuccessCode(aStatus)) {
do_check_eq(aNode.uri, aExpected.url);
}
}
);
break;
case "icon":
let deferred = Promise.defer();
PlacesUtils.favicons.getFaviconDataForPage(
NetUtil.newURI(aExpected.url),
function (aURI, aDataLen, aData, aMimeType) {
let base64Icon = "data:image/png;base64," +
base64EncodeString(String.fromCharCode.apply(String, aData));
do_check_true(base64Icon == aExpected.icon);
deferred.resolve();
});
return deferred.promise;
break;
case "keyword":
break;
case "sidebar":
do_check_eq(PlacesUtils.annotations
.itemHasAnnotation(id, LOAD_IN_SIDEBAR_ANNO),
aExpected.sidebar);
break;
case "postData":
do_check_eq(PlacesUtils.annotations
.getItemAnnotation(id, PlacesUtils.POST_DATA_ANNO),
aExpected.postData);
break;
case "charset":
do_check_eq(PlacesUtils.history.getCharsetForURI(NetUtil.newURI(aNode.uri)),
aExpected.charset);
break;
case "feedUrl":
PlacesUtils.livemarks.getLivemark(
{ id: id },
function (aStatus, aLivemark) {
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark.siteURI.spec, aExpected.url);
do_check_eq(aLivemark.feedURI.spec, Expected.feedUrl);
}
);
break;
case "children":
let folder = aNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
do_check_eq(folder.hasChildren, aExpected.children.length > 0);
folder.containerOpen = true;
do_check_eq(folder.childCount, aExpected.children.length);
break;
case "url":
yield function() {
let deferred = Promise.defer();
PlacesUtils.livemarks.getLivemark(
{ id: id },
function (aStatus, aLivemark) {
if (!Components.isSuccessCode(aStatus)) {
do_check_eq(aNode.uri, aExpected.url);
}
deferred.resolve();
}
);
return deferred.promise; }();
break;
case "icon":
yield function() {
let deferred = Promise.defer();
PlacesUtils.favicons.getFaviconDataForPage(
NetUtil.newURI(aExpected.url),
function (aURI, aDataLen, aData, aMimeType) {
let base64Icon = "data:image/png;base64," +
base64EncodeString(String.fromCharCode.apply(String, aData));
do_check_true(base64Icon == aExpected.icon);
deferred.resolve();
});
return deferred.promise; }();
break;
case "keyword":
break;
case "sidebar":
do_check_eq(PlacesUtils.annotations
.itemHasAnnotation(id, LOAD_IN_SIDEBAR_ANNO),
aExpected.sidebar);
break;
case "postData":
do_check_eq(PlacesUtils.annotations
.getItemAnnotation(id, PlacesUtils.POST_DATA_ANNO),
aExpected.postData);
break;
case "charset":
let testURI = NetUtil.newURI(aNode.uri);
do_check_eq((yield PlacesUtils.getCharsetForURI(testURI)), aExpected.charset);
break;
case "feedUrl":
yield function() {
let deferred = Promise.defer();
PlacesUtils.livemarks.getLivemark(
{ id: id },
function (aStatus, aLivemark) {
do_check_true(Components.isSuccessCode(aStatus));
do_check_eq(aLivemark.siteURI.spec, aExpected.url);
do_check_eq(aLivemark.feedURI.spec, aExpected.feedUrl);
deferred.resolve();
}
);
return deferred.promise; }();
break;
case "children":
let folder = aNode.QueryInterface(Ci.nsINavHistoryContainerResultNode);
do_check_eq(folder.hasChildren, aExpected.children.length > 0);
folder.containerOpen = true;
do_check_eq(folder.childCount, aExpected.children.length);
aExpected.children.forEach(function (item, index) checkItem(item, folder.getChild(index)));
aExpected.children.forEach(function (item, index) checkItem(item, folder.getChild(index)));
folder.containerOpen = false;
break;
default:
throw new Error("Unknown property");
folder.containerOpen = false;
break;
default:
throw new Error("Unknown property");
}
}
};
}).then(deferred.resolve);
return deferred.promise;
}

View File

@ -44,7 +44,7 @@ add_task(function test_corrupt_file() {
true);
// Check that bookmarks that are not corrupt have been imported.
yield database_check();
yield Task.spawn(database_check);
});
add_task(function test_corrupt_database() {
@ -66,7 +66,7 @@ add_task(function test_corrupt_database() {
// Import again and check for correctness.
remove_all_bookmarks();
yield BookmarkHTMLUtils.importFromFile(bookmarksFile, true);
yield database_check();
yield Task.spawn(database_check);
});
/*
@ -129,7 +129,8 @@ function database_check() {
as.getItemAnnotation(testBookmark1.itemId, POST_DATA_ANNO));
// last charset
var testURI = uri(testBookmark1.uri);
do_check_eq("ISO-8859-1", hs.getCharsetForURI(testURI));
do_check_eq((yield PlacesUtils.getCharsetForURI(testURI)), "ISO-8859-1");
// description
do_check_true(as.itemHasAnnotation(testBookmark1.itemId,
DESCRIPTION_ANNO));
@ -175,7 +176,6 @@ function database_check() {
unfiledBookmarks.containerOpen = false;
// favicons
let deferred = Promise.defer();
icos.getFaviconDataForPage(uri(TEST_FAVICON_PAGE_URL),
function DC_onComplete(aURI, aDataLen, aData, aMimeType) {
// aURI should never be null when aDataLen > 0.
@ -184,7 +184,6 @@ function database_check() {
// simplicity, instead of converting the data we receive to a "data:" URI
// and comparing it, we just check the data size.
do_check_eq(TEST_FAVICON_DATA_SIZE, aDataLen);
deferred.resolve();
});
return deferred.promise;
}
);
}