Bug 625684 - Merge fx-sync to mozilla-central. a=blockers

This commit is contained in:
Philipp von Weitershausen 2011-01-14 14:44:53 -08:00
Родитель 1598bb2de6 3b14dfa8f2
Коммит 435ba89db4
16 изменённых файлов: 417 добавлений и 122 удалений

Просмотреть файл

@ -129,6 +129,7 @@ CryptoWrapper.prototype = {
"id: " + this.id, "id: " + this.id,
"index: " + this.sortindex, "index: " + this.sortindex,
"modified: " + this.modified, "modified: " + this.modified,
"ttl: " + this.ttl,
"payload: " + (this.deleted ? "DELETED" : JSON.stringify(this.cleartext)), "payload: " + (this.deleted ? "DELETED" : JSON.stringify(this.cleartext)),
"collection: " + (this.collection || "undefined") "collection: " + (this.collection || "undefined")
].join("\n ") + " }", ].join("\n ") + " }",

Просмотреть файл

@ -98,6 +98,8 @@ WBORecord.prototype = {
let obj = {}; let obj = {};
for (let [key, val] in Iterator(this.data)) for (let [key, val] in Iterator(this.data))
obj[key] = key == "payload" ? JSON.stringify(val) : val; obj[key] = key == "payload" ? JSON.stringify(val) : val;
if (this.ttl)
obj.ttl = this.ttl;
return obj; return obj;
}, },
@ -105,6 +107,7 @@ WBORecord.prototype = {
"id: " + this.id, "id: " + this.id,
"index: " + this.sortindex, "index: " + this.sortindex,
"modified: " + this.modified, "modified: " + this.modified,
"ttl: " + this.ttl,
"payload: " + JSON.stringify(this.payload) "payload: " + JSON.stringify(this.payload)
].join("\n ") + " }", ].join("\n ") + " }",
}; };

Просмотреть файл

@ -325,6 +325,12 @@ BookmarksStore.prototype = {
}, },
applyIncoming: function BStore_applyIncoming(record) { applyIncoming: function BStore_applyIncoming(record) {
// Don't bother with pre and post-processing for deletions.
if (record.deleted) {
Store.prototype.applyIncoming.apply(this, arguments);
return;
}
// For special folders we're only interested in child ordering. // For special folders we're only interested in child ordering.
if ((record.id in kSpecialIds) && record.children) { if ((record.id in kSpecialIds) && record.children) {
this._log.debug("Processing special node: " + record.id); this._log.debug("Processing special node: " + record.id);
@ -367,19 +373,19 @@ BookmarksStore.prototype = {
// Figure out the local id of the parent GUID if available // Figure out the local id of the parent GUID if available
let parentGUID = record.parentid; let parentGUID = record.parentid;
record._orphan = false; if (!parentGUID) {
if (parentGUID != null) { throw "Record " + record.id + " has invalid parentid: " + parentGUID;
let parentId = this.idForGUID(parentGUID); }
// Default to unfiled if we don't have the parent yet
if (parentId <= 0) {
this._log.trace("Reparenting to unfiled until parent is synced");
record._orphan = true;
parentId = kSpecialIds.unfiled;
}
let parentId = this.idForGUID(parentGUID);
if (parentId > 0) {
// Save the parent id for modifying the bookmark later // Save the parent id for modifying the bookmark later
record._parent = parentId; record._parent = parentId;
record._orphan = false;
} else {
this._log.trace("Record " + record.id +
" is an orphan: could not find parent " + parentGUID);
record._orphan = true;
} }
// Do the normal processing of incoming records // Do the normal processing of incoming records
@ -396,7 +402,7 @@ BookmarksStore.prototype = {
this._childrenToOrder[record.id] = record.children; this._childrenToOrder[record.id] = record.children;
} }
// Create an annotation to remember that it needs a parent // Create an annotation to remember that it needs reparenting.
if (record._orphan) if (record._orphan)
Utils.anno(itemId, PARENT_ANNO, parentGUID); Utils.anno(itemId, PARENT_ANNO, parentGUID);
} }
@ -421,12 +427,32 @@ BookmarksStore.prototype = {
this._log.debug("Reparenting orphans " + orphans + " to " + parentId); this._log.debug("Reparenting orphans " + orphans + " to " + parentId);
orphans.forEach(function(orphan) { orphans.forEach(function(orphan) {
// Move the orphan to the parent and drop the missing parent annotation // Move the orphan to the parent and drop the missing parent annotation
Svc.Bookmark.moveItem(orphan, parentId, Svc.Bookmark.DEFAULT_INDEX); if (this._reparentItem(orphan, parentId)) {
Svc.Annos.removeItemAnnotation(orphan, PARENT_ANNO); Svc.Annos.removeItemAnnotation(orphan, PARENT_ANNO);
}
}, this); }, this);
}, },
_reparentItem: function _reparentItem(itemId, parentId) {
this._log.trace("Attempting to move item " + itemId + " to new parent " +
parentId);
try {
if (parentId > 0) {
Svc.Bookmark.moveItem(itemId, parentId, Svc.Bookmark.DEFAULT_INDEX);
return true;
}
} catch(ex) {
this._log.debug("Failed to reparent item. " + Utils.exceptionStr(ex));
}
return false;
},
create: function BStore_create(record) { create: function BStore_create(record) {
// Default to unfiled if we don't have the parent yet
if (!record._parent) {
record._parent = kSpecialIds.unfiled;
}
let newId; let newId;
switch (record.type) { switch (record.type) {
case "bookmark": case "bookmark":
@ -438,7 +464,9 @@ BookmarksStore.prototype = {
this._log.debug(["created bookmark", newId, "under", record._parent, this._log.debug(["created bookmark", newId, "under", record._parent,
"as", record.title, record.bmkUri].join(" ")); "as", record.title, record.bmkUri].join(" "));
this._tagURI(uri, record.tags); if (Utils.isArray(record.tags)) {
this._tagURI(uri, record.tags);
}
this._bms.setKeywordForBookmark(newId, record.keyword); this._bms.setKeywordForBookmark(newId, record.keyword);
if (record.description) if (record.description)
Utils.anno(newId, "bookmarkProperties/description", record.description); Utils.anno(newId, "bookmarkProperties/description", record.description);
@ -540,26 +568,30 @@ BookmarksStore.prototype = {
this._log.trace("Updating " + record.id + " (" + itemId + ")"); this._log.trace("Updating " + record.id + " (" + itemId + ")");
// Move the bookmark to a new parent or new position if necessary // Move the bookmark to a new parent or new position if necessary
if (Svc.Bookmark.getFolderIdForItem(itemId) != record._parent) { if (record._parent > 0 &&
this._log.trace("Moving item to a new parent."); Svc.Bookmark.getFolderIdForItem(itemId) != record._parent) {
Svc.Bookmark.moveItem(itemId, record._parent, Svc.Bookmark.DEFAULT_INDEX); this._reparentItem(itemId, record._parent);
} }
for (let [key, val] in Iterator(record.cleartext)) { for (let [key, val] in Iterator(record.cleartext)) {
switch (key) { switch (key) {
case "title": case "title":
val = val || "";
this._bms.setItemTitle(itemId, val); this._bms.setItemTitle(itemId, val);
break; break;
case "bmkUri": case "bmkUri":
this._bms.changeBookmarkURI(itemId, Utils.makeURI(val)); this._bms.changeBookmarkURI(itemId, Utils.makeURI(val));
break; break;
case "tags": case "tags":
this._tagURI(this._bms.getBookmarkURI(itemId), val); if (Utils.isArray(val)) {
this._tagURI(this._bms.getBookmarkURI(itemId), val);
}
break; break;
case "keyword": case "keyword":
this._bms.setKeywordForBookmark(itemId, val); this._bms.setKeywordForBookmark(itemId, val);
break; break;
case "description": case "description":
val = val || "";
Utils.anno(itemId, "bookmarkProperties/description", val); Utils.anno(itemId, "bookmarkProperties/description", val);
break; break;
case "loadInSidebar": case "loadInSidebar":
@ -644,7 +676,7 @@ BookmarksStore.prototype = {
try { try {
return Utils.anno(id, "bookmarkProperties/description"); return Utils.anno(id, "bookmarkProperties/description");
} catch (e) { } catch (e) {
return undefined; return null;
} }
}, },

Просмотреть файл

@ -47,6 +47,8 @@ Cu.import("resource://services-sync/stores.js");
Cu.import("resource://services-sync/type_records/clients.js"); Cu.import("resource://services-sync/type_records/clients.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
const CLIENTS_TTL_REFRESH = 604800; // 7 days
Utils.lazy(this, "Clients", ClientEngine); Utils.lazy(this, "Clients", ClientEngine);
function ClientEngine() { function ClientEngine() {
@ -63,6 +65,13 @@ ClientEngine.prototype = {
// Always sync client data as it controls other sync behavior // Always sync client data as it controls other sync behavior
get enabled() true, get enabled() true,
get lastRecordUpload() {
return Svc.Prefs.get(this.name + ".lastRecordUpload", 0);
},
set lastRecordUpload(value) {
Svc.Prefs.set(this.name + ".lastRecordUpload", Math.floor(value));
},
// Aggregate some stats on the composition of clients on this account // Aggregate some stats on the composition of clients on this account
get stats() { get stats() {
let stats = { let stats = {
@ -150,6 +159,15 @@ ClientEngine.prototype = {
return false; return false;
}, },
_syncStartup: function _syncStartup() {
// Reupload new client record periodically.
if (Date.now() / 1000 - this.lastRecordUpload > CLIENTS_TTL_REFRESH) {
this._tracker.addChangedID(this.localID);
this.lastRecordUpload = Date.now() / 1000;
}
SyncEngine.prototype._syncStartup.call(this);
},
// Always process incoming items because they might have commands // Always process incoming items because they might have commands
_reconcile: function _reconcile() { _reconcile: function _reconcile() {
return true; return true;

Просмотреть файл

@ -44,12 +44,15 @@ const Cu = Components.utils;
Cu.import("resource://services-sync/base_records/crypto.js"); Cu.import("resource://services-sync/base_records/crypto.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
const CLIENTS_TTL = 1814400; // 21 days
function ClientsRec(collection, id) { function ClientsRec(collection, id) {
CryptoWrapper.call(this, collection, id); CryptoWrapper.call(this, collection, id);
} }
ClientsRec.prototype = { ClientsRec.prototype = {
__proto__: CryptoWrapper.prototype, __proto__: CryptoWrapper.prototype,
_logName: "Record.Clients", _logName: "Record.Clients",
ttl: CLIENTS_TTL
}; };
Utils.deferGetSet(ClientsRec, "cleartext", ["name", "type", "commands"]); Utils.deferGetSet(ClientsRec, "cleartext", ["name", "type", "commands"]);

Просмотреть файл

@ -44,12 +44,15 @@ const Cu = Components.utils;
Cu.import("resource://services-sync/base_records/crypto.js"); Cu.import("resource://services-sync/base_records/crypto.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
const FORMS_TTL = 5184000; // 60 days
function FormRec(collection, id) { function FormRec(collection, id) {
CryptoWrapper.call(this, collection, id); CryptoWrapper.call(this, collection, id);
} }
FormRec.prototype = { FormRec.prototype = {
__proto__: CryptoWrapper.prototype, __proto__: CryptoWrapper.prototype,
_logName: "Record.Form", _logName: "Record.Form",
ttl: FORMS_TTL
}; };
Utils.deferGetSet(FormRec, "cleartext", ["name", "value"]); Utils.deferGetSet(FormRec, "cleartext", ["name", "value"]);

Просмотреть файл

@ -44,12 +44,15 @@ const Cu = Components.utils;
Cu.import("resource://services-sync/base_records/crypto.js"); Cu.import("resource://services-sync/base_records/crypto.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
const HISTORY_TTL = 5184000; // 60 days
function HistoryRec(collection, id) { function HistoryRec(collection, id) {
CryptoWrapper.call(this, collection, id); CryptoWrapper.call(this, collection, id);
} }
HistoryRec.prototype = { HistoryRec.prototype = {
__proto__: CryptoWrapper.prototype, __proto__: CryptoWrapper.prototype,
_logName: "Record.History", _logName: "Record.History",
ttl: HISTORY_TTL
}; };
Utils.deferGetSet(HistoryRec, "cleartext", ["histUri", "title", "visits"]); Utils.deferGetSet(HistoryRec, "cleartext", ["histUri", "title", "visits"]);

Просмотреть файл

@ -44,12 +44,15 @@ const Cu = Components.utils;
Cu.import("resource://services-sync/base_records/crypto.js"); Cu.import("resource://services-sync/base_records/crypto.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
const TABS_TTL = 604800; // 7 days
function TabSetRecord(collection, id) { function TabSetRecord(collection, id) {
CryptoWrapper.call(this, collection, id); CryptoWrapper.call(this, collection, id);
} }
TabSetRecord.prototype = { TabSetRecord.prototype = {
__proto__: CryptoWrapper.prototype, __proto__: CryptoWrapper.prototype,
_logName: "Record.Tabs", _logName: "Record.Tabs",
ttl: TABS_TTL
}; };
Utils.deferGetSet(TabSetRecord, "cleartext", ["clientName", "tabs"]); Utils.deferGetSet(TabSetRecord, "cleartext", ["clientName", "tabs"]);

Просмотреть файл

@ -7,6 +7,13 @@ function httpd_setup (handlers) {
return server; return server;
} }
function httpd_handler(statusCode, status, body) {
return function(request, response) {
response.setStatusLine(request.httpVersion, statusCode, status);
response.bodyOutputStream.write(body, body.length);
};
}
function httpd_basic_auth_handler(body, metadata, response) { function httpd_basic_auth_handler(body, metadata, response) {
// no btoa() in xpcshell. it's guest:guest // no btoa() in xpcshell. it's guest:guest
if (metadata.hasHeader("Authorization") && if (metadata.hasHeader("Authorization") &&
@ -123,8 +130,9 @@ function ServerCollection(wbos) {
ServerCollection.prototype = { ServerCollection.prototype = {
_inResultSet: function(wbo, options) { _inResultSet: function(wbo, options) {
return ((!options.ids || (options.ids.indexOf(wbo.id) != -1)) return wbo.payload
&& (!options.newer || (wbo.modified > options.newer))); && (!options.ids || (options.ids.indexOf(wbo.id) != -1))
&& (!options.newer || (wbo.modified > options.newer));
}, },
get: function(options) { get: function(options) {

Просмотреть файл

@ -3,12 +3,15 @@ Cu.import("resource://services-sync/engines/bookmarks.js");
Cu.import("resource://services-sync/type_records/bookmark.js"); Cu.import("resource://services-sync/type_records/bookmark.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
const PARENT_ANNO = "sync/parent";
Engines.register(BookmarksEngine); Engines.register(BookmarksEngine);
let engine = Engines.get("bookmarks"); let engine = Engines.get("bookmarks");
let store = engine._store; let store = engine._store;
let fxuri = Utils.makeURI("http://getfirefox.com/"); let fxuri = Utils.makeURI("http://getfirefox.com/");
let tburi = Utils.makeURI("http://getthunderbird.com/"); let tburi = Utils.makeURI("http://getthunderbird.com/");
function test_bookmark_create() { function test_bookmark_create() {
try { try {
_("Ensure the record isn't present yet."); _("Ensure the record isn't present yet.");
@ -31,7 +34,10 @@ function test_bookmark_create() {
let id = store.idForGUID(fxrecord.id); let id = store.idForGUID(fxrecord.id);
do_check_eq(store.GUIDForId(id), fxrecord.id); do_check_eq(store.GUIDForId(id), fxrecord.id);
do_check_eq(Svc.Bookmark.getItemType(id), Svc.Bookmark.TYPE_BOOKMARK); do_check_eq(Svc.Bookmark.getItemType(id), Svc.Bookmark.TYPE_BOOKMARK);
do_check_true(Svc.Bookmark.getBookmarkURI(id).equals(fxuri));
do_check_eq(Svc.Bookmark.getItemTitle(id), fxrecord.title); do_check_eq(Svc.Bookmark.getItemTitle(id), fxrecord.title);
do_check_eq(Utils.anno(id, "bookmarkProperties/description"),
fxrecord.description);
do_check_eq(Svc.Bookmark.getFolderIdForItem(id), do_check_eq(Svc.Bookmark.getFolderIdForItem(id),
Svc.Bookmark.toolbarFolder); Svc.Bookmark.toolbarFolder);
do_check_eq(Svc.Bookmark.getKeywordForBookmark(id), fxrecord.keyword); do_check_eq(Svc.Bookmark.getKeywordForBookmark(id), fxrecord.keyword);
@ -40,13 +46,85 @@ function test_bookmark_create() {
let newrecord = store.createRecord(fxrecord.id); let newrecord = store.createRecord(fxrecord.id);
do_check_true(newrecord instanceof Bookmark); do_check_true(newrecord instanceof Bookmark);
for each (let property in ["type", "bmkUri", "description", "title", for each (let property in ["type", "bmkUri", "description", "title",
"keyword", "parentName", "parentid"]) "keyword", "parentName", "parentid"]) {
do_check_eq(newrecord[property], fxrecord[property]); do_check_eq(newrecord[property], fxrecord[property]);
}
do_check_true(Utils.deepEquals(newrecord.tags.sort(), do_check_true(Utils.deepEquals(newrecord.tags.sort(),
fxrecord.tags.sort())); fxrecord.tags.sort()));
_("The calculated sort index is based on frecency data."); _("The calculated sort index is based on frecency data.");
do_check_true(newrecord.sortindex >= 150); do_check_true(newrecord.sortindex >= 150);
_("Create a record with some values missing.");
let tbrecord = new Bookmark("bookmarks", "thunderbird1");
tbrecord.bmkUri = tburi.spec;
tbrecord.parentName = "Bookmarks Toolbar";
tbrecord.parentid = "toolbar";
store.applyIncoming(tbrecord);
_("Verify it has been created correctly.");
id = store.idForGUID(tbrecord.id);
do_check_eq(store.GUIDForId(id), tbrecord.id);
do_check_eq(Svc.Bookmark.getItemType(id), Svc.Bookmark.TYPE_BOOKMARK);
do_check_true(Svc.Bookmark.getBookmarkURI(id).equals(tburi));
do_check_eq(Svc.Bookmark.getItemTitle(id), null);
let error;
try {
Utils.anno(id, "bookmarkProperties/description");
} catch(ex) {
error = ex;
}
do_check_eq(error.result, Cr.NS_ERROR_NOT_AVAILABLE);
do_check_eq(Svc.Bookmark.getFolderIdForItem(id),
Svc.Bookmark.toolbarFolder);
do_check_eq(Svc.Bookmark.getKeywordForBookmark(id), null);
} finally {
_("Clean up.");
store.wipe();
}
}
function test_bookmark_update() {
try {
_("Create a bookmark whose values we'll change.");
let bmk1_id = Svc.Bookmark.insertBookmark(
Svc.Bookmark.toolbarFolder, fxuri, Svc.Bookmark.DEFAULT_INDEX,
"Get Firefox!");
Utils.anno(bmk1_id, "bookmarkProperties/description", "Firefox is awesome.");
Svc.Bookmark.setKeywordForBookmark(bmk1_id, "firefox");
let bmk1_guid = store.GUIDForId(bmk1_id);
_("Update the record with some null values.");
let record = store.createRecord(bmk1_guid);
record.title = null;
record.description = null;
record.keyword = null;
record.tags = null;
store.applyIncoming(record);
_("Verify that the values have been cleared.");
do_check_eq(Utils.anno(bmk1_id, "bookmarkProperties/description"), "");
do_check_eq(Svc.Bookmark.getItemTitle(bmk1_id), "");
do_check_eq(Svc.Bookmark.getKeywordForBookmark(bmk1_id), null);
} finally {
_("Clean up.");
store.wipe();
}
}
function test_bookmark_createRecord() {
try {
_("Create a bookmark without a description or title.");
let bmk1_id = Svc.Bookmark.insertBookmark(
Svc.Bookmark.toolbarFolder, fxuri, Svc.Bookmark.DEFAULT_INDEX, null);
let bmk1_guid = store.GUIDForId(bmk1_id);
_("Verify that the record is created accordingly.");
let record = store.createRecord(bmk1_guid);
do_check_eq(record.title, null);
do_check_eq(record.description, null);
do_check_eq(record.keyword, null);
} finally { } finally {
_("Clean up."); _("Clean up.");
store.wipe(); store.wipe();
@ -116,6 +194,37 @@ function test_folder_createRecord() {
} }
} }
function test_deleted() {
try {
_("Create a bookmark that will be deleted.");
let bmk1_id = Svc.Bookmark.insertBookmark(
Svc.Bookmark.toolbarFolder, fxuri, Svc.Bookmark.DEFAULT_INDEX,
"Get Firefox!");
let bmk1_guid = store.GUIDForId(bmk1_id);
_("Delete the bookmark through the store.");
let record = new PlacesItem("bookmarks", bmk1_guid);
record.deleted = true;
store.applyIncoming(record);
_("Ensure it has been deleted.");
let error;
try {
Svc.Bookmark.getBookmarkURI(bmk1_id);
} catch(ex) {
error = ex;
}
do_check_eq(error.result, Cr.NS_ERROR_ILLEGAL_VALUE);
let newrec = store.createRecord(bmk1_guid);
do_check_eq(newrec.deleted, true);
} finally {
_("Clean up.");
store.wipe();
}
}
function test_move_folder() { function test_move_folder() {
try { try {
_("Create two folders and a bookmark in one of them."); _("Create two folders and a bookmark in one of them.");
@ -133,7 +242,6 @@ function test_move_folder() {
let record = store.createRecord(bmk_guid); let record = store.createRecord(bmk_guid);
do_check_eq(record.parentid, folder1_guid); do_check_eq(record.parentid, folder1_guid);
record.parentid = folder2_guid; record.parentid = folder2_guid;
record.description = ""; //TODO for some reason we need this
store.applyIncoming(record); store.applyIncoming(record);
_("Verify the new parent."); _("Verify the new parent.");
@ -188,10 +296,69 @@ function test_move_order() {
} }
} }
function test_orphan() {
try {
_("Add a new bookmark locally.");
let bmk1_id = Svc.Bookmark.insertBookmark(
Svc.Bookmark.toolbarFolder, fxuri, Svc.Bookmark.DEFAULT_INDEX,
"Get Firefox!");
let bmk1_guid = store.GUIDForId(bmk1_id);
do_check_eq(Svc.Bookmark.getFolderIdForItem(bmk1_id), Svc.Bookmark.toolbarFolder);
let error;
try {
Utils.anno(bmk1_id, PARENT_ANNO);
} catch(ex) {
error = ex;
}
do_check_eq(error.result, Cr.NS_ERROR_NOT_AVAILABLE);
_("Apply a server record that is the same but refers to non-existent folder.");
let record = store.createRecord(bmk1_guid);
record.parentid = "non-existent";
store.applyIncoming(record);
_("Verify that bookmark has been flagged as orphan, has not moved.");
do_check_eq(Svc.Bookmark.getFolderIdForItem(bmk1_id), Svc.Bookmark.toolbarFolder);
do_check_eq(Utils.anno(bmk1_id, PARENT_ANNO), "non-existent");
} finally {
_("Clean up.");
store.wipe();
}
}
function test_reparentOrphans() {
try {
let folder1_id = Svc.Bookmark.createFolder(
Svc.Bookmark.toolbarFolder, "Folder1", 0);
let folder1_guid = store.GUIDForId(folder1_id);
_("Create a bogus orphan record and write the record back to the store to trigger _reparentOrphans.");
Utils.anno(folder1_id, PARENT_ANNO, folder1_guid);
let record = store.createRecord(folder1_guid);
record.title = "New title for Folder 1";
store._childrenToOrder = {};
store.applyIncoming(record);
_("Verify that is has been marked as an orphan even though it couldn't be moved into itself.");
do_check_eq(Utils.anno(folder1_id, PARENT_ANNO), folder1_guid);
} finally {
_("Clean up.");
store.wipe();
}
}
function run_test() { function run_test() {
test_bookmark_create(); test_bookmark_create();
test_bookmark_createRecord();
test_bookmark_update();
test_folder_create(); test_folder_create();
test_folder_createRecord(); test_folder_createRecord();
test_deleted();
test_move_folder(); test_move_folder();
test_move_order(); test_move_order();
test_orphan();
test_reparentOrphans();
} }

Просмотреть файл

@ -0,0 +1,80 @@
Cu.import("resource://services-sync/constants.js");
Cu.import("resource://services-sync/base_records/crypto.js");
Cu.import("resource://services-sync/base_records/wbo.js");
Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/engines/clients.js");
const MORE_THAN_CLIENTS_TTL_REFRESH = 691200; // 8 days
const LESS_THAN_CLIENTS_TTL_REFRESH = 86400; // 1 day
function test_properties() {
try {
_("Test lastRecordUpload property");
do_check_eq(Svc.Prefs.get("clients.lastRecordUpload"), undefined);
do_check_eq(Clients.lastRecordUpload, 0);
let now = Date.now();
Clients.lastRecordUpload = now / 1000;
do_check_eq(Clients.lastRecordUpload, Math.floor(now / 1000));
} finally {
Svc.Prefs.resetBranch("");
}
}
function test_sync() {
_("Ensure that Clients engine uploads a new client record once a week.");
Svc.Prefs.set("clusterURL", "http://localhost:8080/");
Svc.Prefs.set("username", "foo");
new SyncTestingInfrastructure();
CollectionKeys.generateNewKeys();
let global = new ServerWBO('global',
{engines: {clients: {version: Clients.version,
syncID: Clients.syncID}}});
let coll = new ServerCollection();
let clientwbo = coll.wbos[Clients.localID] = new ServerWBO(Clients.localID);
let server = httpd_setup({
"/1.0/foo/storage/meta/global": global.handler(),
"/1.0/foo/storage/clients": coll.handler()
});
do_test_pending();
try {
_("First sync, client record is uploaded");
do_check_eq(clientwbo.payload, undefined);
do_check_eq(Clients.lastRecordUpload, 0);
Clients.sync();
do_check_true(!!clientwbo.payload);
do_check_true(Clients.lastRecordUpload > 0);
_("Let's time travel more than a week back, new record should've been uploaded.");
Clients.lastRecordUpload -= MORE_THAN_CLIENTS_TTL_REFRESH;
let lastweek = Clients.lastRecordUpload;
clientwbo.payload = undefined;
Clients.sync();
do_check_true(!!clientwbo.payload);
do_check_true(Clients.lastRecordUpload > lastweek);
_("Time travel one day back, no record uploaded.");
Clients.lastRecordUpload -= LESS_THAN_CLIENTS_TTL_REFRESH;
let yesterday = Clients.lastRecordUpload;
clientwbo.payload = undefined;
Clients.sync();
do_check_eq(clientwbo.payload, undefined);
do_check_eq(Clients.lastRecordUpload, yesterday);
} finally {
server.stop(do_test_finished);
Svc.Prefs.resetBranch("");
Records.clearCache();
}
}
function run_test() {
test_properties();
test_sync();
}

Просмотреть файл

@ -1,67 +1,62 @@
try { Cu.import("resource://services-sync/auth.js");
Cu.import("resource://services-sync/auth.js"); Cu.import("resource://services-sync/base_records/wbo.js");
Cu.import("resource://services-sync/base_records/wbo.js"); Cu.import("resource://services-sync/base_records/collection.js");
Cu.import("resource://services-sync/base_records/collection.js"); Cu.import("resource://services-sync/identity.js");
Cu.import("resource://services-sync/identity.js"); Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/log4moz.js"); Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/resource.js");
Cu.import("resource://services-sync/util.js");
} catch (e) { do_throw(e); }
function record_handler(metadata, response) {
let obj = {id: "asdf-1234-asdf-1234", function test_toJSON() {
modified: 2454725.98283, _("Create a record, for now without a TTL.");
payload: JSON.stringify({cheese: "roquefort"})}; let wbo = new WBORecord("coll", "a_record");
return httpd_basic_auth_handler(JSON.stringify(obj), metadata, response); wbo.modified = 12345;
wbo.sortindex = 42;
wbo.payload = {};
_("Verify that the JSON representation contains the WBO properties, but not TTL.");
let json = JSON.parse(JSON.stringify(wbo));
do_check_eq(json.modified, 12345);
do_check_eq(json.sortindex, 42);
do_check_eq(json.payload, "{}");
do_check_false("ttl" in json);
_("Set a TTL, make sure it's present in the JSON representation.");
wbo.ttl = 30*60;
json = JSON.parse(JSON.stringify(wbo));
do_check_eq(json.ttl, 30*60);
} }
function record_handler2(metadata, response) {
let obj = {id: "record2",
modified: 2454725.98284,
payload: JSON.stringify({cheese: "gruyere"})};
return httpd_basic_auth_handler(JSON.stringify(obj), metadata, response);
}
function coll_handler(metadata, response) { function test_fetch() {
let obj = [{id: "record2", let record = {id: "asdf-1234-asdf-1234",
modified: 2454725.98284, modified: 2454725.98283,
payload: JSON.stringify({cheese: "gruyere"})}]; payload: JSON.stringify({cheese: "roquefort"})};
return httpd_basic_auth_handler(JSON.stringify(obj), metadata, response); let record2 = {id: "record2",
} modified: 2454725.98284,
payload: JSON.stringify({cheese: "gruyere"})};
let coll = [{id: "record2",
modified: 2454725.98284,
payload: JSON.stringify({cheese: "gruyere"})}];
function run_test() { _("Setting up server.");
let server; let server = httpd_setup({
"/record": httpd_handler(200, "OK", JSON.stringify(record)),
"/record2": httpd_handler(200, "OK", JSON.stringify(record2)),
"/coll": httpd_handler(200, "OK", JSON.stringify(coll))
});
do_test_pending(); do_test_pending();
try { try {
let log = Log4Moz.repository.getLogger('Test'); _("Fetching a WBO record");
Log4Moz.repository.rootLogger.addAppender(new Log4Moz.DumpAppender());
log.info("Setting up server and authenticator");
server = httpd_setup({"/record": record_handler,
"/record2": record_handler2,
"/coll": coll_handler});
let auth = new BasicAuthenticator(new Identity("secret", "guest", "guest"));
Auth.defaultAuthenticator = auth;
log.info("Getting a WBO record");
let res = new Resource("http://localhost:8080/record");
let resp = res.get();
let rec = new WBORecord("coll", "record"); let rec = new WBORecord("coll", "record");
rec.deserialize(res.data); rec.fetch("http://localhost:8080/record");
do_check_eq(rec.id, "asdf-1234-asdf-1234"); // NOT "record"! do_check_eq(rec.id, "asdf-1234-asdf-1234"); // NOT "record"!
do_check_eq(rec.modified, 2454725.98283); do_check_eq(rec.modified, 2454725.98283);
do_check_eq(typeof(rec.payload), "object"); do_check_eq(typeof(rec.payload), "object");
do_check_eq(rec.payload.cheese, "roquefort"); do_check_eq(rec.payload.cheese, "roquefort");
do_check_eq(resp.status, 200);
log.info("Getting a WBO record using the record manager");
_("Fetching a WBO record using the record manager");
let rec2 = Records.get("http://localhost:8080/record2"); let rec2 = Records.get("http://localhost:8080/record2");
do_check_eq(rec2.id, "record2"); do_check_eq(rec2.id, "record2");
do_check_eq(rec2.modified, 2454725.98284); do_check_eq(rec2.modified, 2454725.98284);
@ -70,11 +65,18 @@ function run_test() {
do_check_eq(Records.response.status, 200); do_check_eq(Records.response.status, 200);
// Testing collection extraction. // Testing collection extraction.
log.info("Extracting collection."); _("Extracting collection.");
let rec3 = new WBORecord("tabs", "foo"); // Create through constructor. let rec3 = new WBORecord("tabs", "foo"); // Create through constructor.
do_check_eq(rec3.collection, "tabs"); do_check_eq(rec3.collection, "tabs");
log.info("Done!");
} finally {
server.stop(do_test_finished);
} }
catch (e) { do_throw(e); } }
finally { server.stop(do_test_finished); }
function run_test() {
initTestLogging("Trace");
test_toJSON();
test_fetch();
} }

Просмотреть файл

@ -1,22 +1,15 @@
Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
function send(statusCode, status, body) {
return function(request, response) {
response.setStatusLine(request.httpVersion, statusCode, status);
response.bodyOutputStream.write(body, body.length);
};
}
function run_test() { function run_test() {
do_test_pending(); do_test_pending();
let server = httpd_setup({ let server = httpd_setup({
"/user/1.0/johndoe": send(200, "OK", "1"), "/user/1.0/johndoe": httpd_handler(200, "OK", "1"),
"/user/1.0/janedoe": send(200, "OK", "0"), "/user/1.0/janedoe": httpd_handler(200, "OK", "0"),
// john@doe.com // john@doe.com
"/user/1.0/7wohs32cngzuqt466q3ge7indszva4of": send(200, "OK", "0"), "/user/1.0/7wohs32cngzuqt466q3ge7indszva4of": httpd_handler(200, "OK", "0"),
// jane@doe.com // jane@doe.com
"/user/1.0/vuuf3eqgloxpxmzph27f5a6ve7gzlrms": send(200, "OK", "1") "/user/1.0/vuuf3eqgloxpxmzph27f5a6ve7gzlrms": httpd_handler(200, "OK", "1")
}); });
try { try {
Service.serverURL = "http://localhost:8080/"; Service.serverURL = "http://localhost:8080/";

Просмотреть файл

@ -11,13 +11,6 @@ function do_check_throws(func) {
do_check_true(raised); do_check_true(raised);
} }
function send(statusCode, status, body) {
return function(request, response) {
response.setStatusLine(request.httpVersion, statusCode, status);
response.bodyOutputStream.write(body, body.length);
};
}
function test_findCluster() { function test_findCluster() {
_("Test Service._findCluster()"); _("Test Service._findCluster()");
let server; let server;
@ -31,11 +24,11 @@ function test_findCluster() {
}); });
server = httpd_setup({ server = httpd_setup({
"/user/1.0/johndoe/node/weave": send(200, "OK", "http://weave.user.node/"), "/user/1.0/johndoe/node/weave": httpd_handler(200, "OK", "http://weave.user.node/"),
"/user/1.0/jimdoe/node/weave": send(200, "OK", "null"), "/user/1.0/jimdoe/node/weave": httpd_handler(200, "OK", "null"),
"/user/1.0/janedoe/node/weave": send(404, "Not Found", "Not Found"), "/user/1.0/janedoe/node/weave": httpd_handler(404, "Not Found", "Not Found"),
"/user/1.0/juliadoe/node/weave": send(400, "Bad Request", "Bad Request"), "/user/1.0/juliadoe/node/weave": httpd_handler(400, "Bad Request", "Bad Request"),
"/user/1.0/joedoe/node/weave": send(500, "Server Error", "Server Error") "/user/1.0/joedoe/node/weave": httpd_handler(500, "Server Error", "Server Error")
}); });
_("_findCluster() returns the user's cluster node"); _("_findCluster() returns the user's cluster node");
@ -76,8 +69,8 @@ function test_findCluster() {
function test_setCluster() { function test_setCluster() {
_("Test Service._setCluster()"); _("Test Service._setCluster()");
let server = httpd_setup({ let server = httpd_setup({
"/user/1.0/johndoe/node/weave": send(200, "OK", "http://weave.user.node/"), "/user/1.0/johndoe/node/weave": httpd_handler(200, "OK", "http://weave.user.node/"),
"/user/1.0/jimdoe/node/weave": send(200, "OK", "null") "/user/1.0/jimdoe/node/weave": httpd_handler(200, "OK", "null")
}); });
try { try {
Service.serverURL = "http://localhost:8080/"; Service.serverURL = "http://localhost:8080/";
@ -108,8 +101,8 @@ function test_setCluster() {
function test_updateCluster() { function test_updateCluster() {
_("Test Service._updateCluster()"); _("Test Service._updateCluster()");
let server = httpd_setup({ let server = httpd_setup({
"/user/1.0/johndoe/node/weave": send(200, "OK", "http://weave.user.node/"), "/user/1.0/johndoe/node/weave": httpd_handler(200, "OK", "http://weave.user.node/"),
"/user/1.0/janedoe/node/weave": send(200, "OK", "http://weave.cluster.url/") "/user/1.0/janedoe/node/weave": httpd_handler(200, "OK", "http://weave.cluster.url/")
}); });
try { try {
Service.serverURL = "http://localhost:8080/"; Service.serverURL = "http://localhost:8080/";

Просмотреть файл

@ -1,13 +1,6 @@
Cu.import("resource://services-sync/service.js"); Cu.import("resource://services-sync/service.js");
Cu.import("resource://services-sync/util.js"); Cu.import("resource://services-sync/util.js");
function send(body) {
return function(request, response) {
response.setStatusLine(request.httpVersion, 200, "OK");
response.bodyOutputStream.write(body, body.length);
};
}
function run_test() { function run_test() {
let collection_usage = {steam: 65.11328, let collection_usage = {steam: 65.11328,
petrol: 82.488281, petrol: 82.488281,
@ -16,10 +9,10 @@ function run_test() {
do_test_pending(); do_test_pending();
let server = httpd_setup({ let server = httpd_setup({
"/1.0/johndoe/info/collection_usage": send(JSON.stringify(collection_usage)), "/1.0/johndoe/info/collection_usage": httpd_handler(200, "OK", JSON.stringify(collection_usage)),
"/1.0/johndoe/info/quota": send(JSON.stringify(quota)), "/1.0/johndoe/info/quota": httpd_handler(200, "OK", JSON.stringify(quota)),
"/1.0/janedoe/info/collection_usage": send("gargabe"), "/1.0/janedoe/info/collection_usage": httpd_handler(200, "OK", "gargabe"),
"/1.0/janedoe/info/quota": send("more garbage") "/1.0/janedoe/info/quota": httpd_handler(200, "OK", "more garbage")
}); });
try { try {

Просмотреть файл

@ -18,13 +18,6 @@ function login_handler(request, response) {
response.bodyOutputStream.write(body, body.length); response.bodyOutputStream.write(body, body.length);
} }
function send(statusCode, status, body) {
return function(request, response) {
response.setStatusLine(request.httpVersion, statusCode, status);
response.bodyOutputStream.write(body, body.length);
};
}
function service_unavailable(request, response) { function service_unavailable(request, response) {
let body = "Service Unavailable"; let body = "Service Unavailable";
response.setStatusLine(request.httpVersion, 503, "Service Unavailable"); response.setStatusLine(request.httpVersion, 503, "Service Unavailable");
@ -45,7 +38,7 @@ function run_test() {
"/api/1.0/janedoe/info/collections": service_unavailable, "/api/1.0/janedoe/info/collections": service_unavailable,
"/api/1.0/johndoe/storage/meta/global": new ServerWBO().handler(), "/api/1.0/johndoe/storage/meta/global": new ServerWBO().handler(),
"/api/1.0/johndoe/storage/crypto/keys": new ServerWBO().handler(), "/api/1.0/johndoe/storage/crypto/keys": new ServerWBO().handler(),
"/user/1.0/johndoe/node/weave": send(200, "OK", "http://localhost:8080/api/") "/user/1.0/johndoe/node/weave": httpd_handler(200, "OK", "http://localhost:8080/api/")
}); });
try { try {