зеркало из https://github.com/mozilla/gecko-dev.git
Merge fx-sync to mozilla-central (bug 597426)
This commit is contained in:
Коммит
4a2ae4efbe
|
@ -28,6 +28,8 @@ error.sync.title = Error While Syncing
|
|||
error.sync.description = Sync encountered an error while syncing: %1$S. Sync will automatically retry this action.
|
||||
error.sync.no_node_found = The Sync server is a little busy right now, but you don't need to do anything about it. We'll start syncing your data as soon as we can!
|
||||
error.sync.no_node_found.title = Sync Delay
|
||||
error.sync.serverStatusButton.label = Server Status
|
||||
error.sync.serverStatusButton.accesskey = V
|
||||
error.sync.needUpdate.description = You need to update Firefox Sync to continue syncing your data.
|
||||
error.sync.needUpdate.label = Update Firefox Sync
|
||||
error.sync.needUpdate.accesskey = U
|
||||
|
|
|
@ -138,6 +138,12 @@ Collection.prototype = {
|
|||
// Save this because onProgress is called with this as the ChannelListener
|
||||
let coll = this;
|
||||
|
||||
// Prepare a dummyUri so that records can generate the correct
|
||||
// relative URLs. The last bit will be replaced with record.id.
|
||||
let dummyUri = this.uri.clone().QueryInterface(Ci.nsIURL);
|
||||
dummyUri.filePath += "/replaceme";
|
||||
dummyUri.query = "";
|
||||
|
||||
// Switch to newline separated records for incremental parsing
|
||||
coll.setHeader("Accept", "application/newlines");
|
||||
|
||||
|
@ -149,9 +155,8 @@ Collection.prototype = {
|
|||
this._data = this._data.slice(newline + 1);
|
||||
|
||||
// Deserialize a record from json and give it to the callback
|
||||
let record = new coll._recordObj();
|
||||
let record = new coll._recordObj(dummyUri);
|
||||
record.deserialize(json);
|
||||
record.baseUri = coll.uri;
|
||||
onRecord(record);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -49,13 +49,19 @@ Cu.import("resource://services-sync/util.js");
|
|||
function CryptoWrapper(uri) {
|
||||
this.cleartext = {};
|
||||
WBORecord.call(this, uri);
|
||||
this.encryption = "";
|
||||
this.ciphertext = null;
|
||||
}
|
||||
CryptoWrapper.prototype = {
|
||||
__proto__: WBORecord.prototype,
|
||||
_logName: "Record.CryptoWrapper",
|
||||
|
||||
get encryption() {
|
||||
return this.uri.resolve(this.payload.encryption);
|
||||
},
|
||||
set encryption(value) {
|
||||
this.payload.encryption = this.uri.getRelativeSpec(Utils.makeURI(value));
|
||||
},
|
||||
|
||||
encrypt: function CryptoWrapper_encrypt(passphrase) {
|
||||
let pubkey = PubKeys.getDefaultKey();
|
||||
let privkey = PrivKeys.get(pubkey.privateKeyUri);
|
||||
|
@ -109,8 +115,7 @@ CryptoWrapper.prototype = {
|
|||
},
|
||||
};
|
||||
|
||||
Utils.deferGetSet(CryptoWrapper, "payload", ["ciphertext", "encryption", "IV",
|
||||
"hmac"]);
|
||||
Utils.deferGetSet(CryptoWrapper, "payload", ["ciphertext", "IV", "hmac"]);
|
||||
Utils.deferGetSet(CryptoWrapper, "cleartext", "deleted");
|
||||
|
||||
function CryptoMeta(uri) {
|
||||
|
@ -180,7 +185,7 @@ CryptoMeta.prototype = {
|
|||
|
||||
// Wrap the symmetric key and generate a HMAC for it
|
||||
let wrapped = Svc.Crypto.wrapSymmetricKey(symkey, new_pubkey.keyData);
|
||||
this.keyring[new_pubkey.uri.spec] = {
|
||||
this.keyring[this.uri.getRelativeSpec(new_pubkey.uri)] = {
|
||||
wrapped: wrapped,
|
||||
hmac: Utils.sha256HMAC(wrapped, this.hmacKey)
|
||||
};
|
||||
|
|
|
@ -52,7 +52,6 @@ function PubKey(uri) {
|
|||
WBORecord.call(this, uri);
|
||||
this.type = "pubkey";
|
||||
this.keyData = null;
|
||||
this.privateKeyUri = null;
|
||||
}
|
||||
PubKey.prototype = {
|
||||
__proto__: WBORecord.prototype,
|
||||
|
@ -66,13 +65,16 @@ PubKey.prototype = {
|
|||
let key = this.payload.privateKeyUri;
|
||||
return Utils.makeURI(this.uri.resolve(key) || key);
|
||||
},
|
||||
set privateKeyUri(value) {
|
||||
this.payload.privateKeyUri = this.uri.getRelativeSpec(Utils.makeURI(value));
|
||||
},
|
||||
|
||||
get publicKeyUri() {
|
||||
throw "attempted to get public key url from a public key!";
|
||||
}
|
||||
};
|
||||
|
||||
Utils.deferGetSet(PubKey, "payload", ["keyData", "privateKeyUri", "type"]);
|
||||
Utils.deferGetSet(PubKey, "payload", ["keyData", "type"]);
|
||||
|
||||
function PrivKey(uri) {
|
||||
WBORecord.call(this, uri);
|
||||
|
@ -80,7 +82,6 @@ function PrivKey(uri) {
|
|||
this.salt = null;
|
||||
this.iv = null;
|
||||
this.keyData = null;
|
||||
this.publicKeyUri = null;
|
||||
}
|
||||
PrivKey.prototype = {
|
||||
__proto__: WBORecord.prototype,
|
||||
|
@ -94,13 +95,16 @@ PrivKey.prototype = {
|
|||
let key = this.payload.publicKeyUri;
|
||||
return Utils.makeURI(this.uri.resolve(key) || key);
|
||||
},
|
||||
set publicKeyUri(value) {
|
||||
this.payload.publicKeyUri = this.uri.getRelativeSpec(Utils.makeURI(value));
|
||||
},
|
||||
|
||||
get privateKeyUri() {
|
||||
throw "attempted to get private key url from a private key!";
|
||||
}
|
||||
};
|
||||
|
||||
Utils.deferGetSet(PrivKey, "payload", ["salt", "iv", "keyData", "publicKeyUri", "type"]);
|
||||
Utils.deferGetSet(PrivKey, "payload", ["salt", "iv", "keyData", "type"]);
|
||||
|
||||
// XXX unused/unfinished
|
||||
function SymKey(keyData, wrapped) {
|
||||
|
@ -137,9 +141,14 @@ PubKeyManager.prototype = {
|
|||
},
|
||||
|
||||
createKeypair: function KeyMgr_createKeypair(passphrase, pubkeyUri, privkeyUri) {
|
||||
if (!pubkeyUri)
|
||||
throw "Missing or null parameter 'pubkeyUri'.";
|
||||
if (!privkeyUri)
|
||||
throw "Missing or null parameter 'privkeyUri'.";
|
||||
|
||||
this._log.debug("Generating RSA keypair");
|
||||
let pubkey = new PubKey();
|
||||
let privkey = new PrivKey();
|
||||
let pubkey = new PubKey(pubkeyUri);
|
||||
let privkey = new PrivKey(privkeyUri);
|
||||
privkey.salt = Svc.Crypto.generateRandomBytes(16);
|
||||
privkey.iv = Svc.Crypto.generateRandomIV();
|
||||
|
||||
|
@ -148,14 +157,8 @@ PubKeyManager.prototype = {
|
|||
privkey.iv, pub, priv);
|
||||
[pubkey.keyData, privkey.keyData] = [pub.value, priv.value];
|
||||
|
||||
if (pubkeyUri) {
|
||||
pubkey.uri = pubkeyUri;
|
||||
privkey.publicKeyUri = pubkeyUri;
|
||||
}
|
||||
if (privkeyUri) {
|
||||
privkey.uri = privkeyUri;
|
||||
pubkey.privateKeyUri = privkeyUri;
|
||||
}
|
||||
pubkey.privateKeyUri = privkeyUri;
|
||||
privkey.publicKeyUri = pubkeyUri;
|
||||
|
||||
this._log.debug("Generating RSA keypair... done");
|
||||
return {pubkey: pubkey, privkey: privkey};
|
||||
|
|
|
@ -46,10 +46,12 @@ Cu.import("resource://services-sync/resource.js");
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function WBORecord(uri) {
|
||||
if (uri == null)
|
||||
throw "WBOs must have a URI!";
|
||||
|
||||
this.data = {};
|
||||
this.payload = {};
|
||||
if (uri)
|
||||
this.uri = uri;
|
||||
this.uri = uri;
|
||||
}
|
||||
WBORecord.prototype = {
|
||||
_logName: "Record.WBO",
|
||||
|
@ -57,14 +59,14 @@ WBORecord.prototype = {
|
|||
// NOTE: baseUri must have a trailing slash, or baseUri.resolve() will omit
|
||||
// the collection name
|
||||
get uri() {
|
||||
return Utils.makeURI(this.baseUri.resolve(encodeURI(this.id)));
|
||||
return Utils.makeURL(this.baseUri.resolve(encodeURI(this.id)));
|
||||
},
|
||||
set uri(value) {
|
||||
if (typeof(value) != "string")
|
||||
value = value.spec;
|
||||
let foo = value.split('/');
|
||||
this.id = foo.pop();
|
||||
this.baseUri = Utils.makeURI(foo.join('/') + '/');
|
||||
let parts = value.split('/');
|
||||
this.id = parts.pop();
|
||||
this.baseUri = Utils.makeURI(parts.join('/') + '/');
|
||||
},
|
||||
|
||||
get sortindex() {
|
||||
|
@ -122,9 +124,8 @@ RecordManager.prototype = {
|
|||
if (!this.response.success)
|
||||
return null;
|
||||
|
||||
let record = new this._recordType();
|
||||
let record = new this._recordType(url);
|
||||
record.deserialize(this.response);
|
||||
record.uri = url;
|
||||
|
||||
return this.set(url, record);
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ WEAVE_ID: "@weave_id@",
|
|||
// Version of the data format this client supports. The data format describes
|
||||
// how records are packaged; this is separate from the Server API version and
|
||||
// the per-engine cleartext formats.
|
||||
STORAGE_VERSION: 2,
|
||||
STORAGE_VERSION: 3,
|
||||
|
||||
UPDATED_DEV_URL: "https://services.mozilla.com/sync/updated/?version=@weave_version@&channel=@xpi_type@",
|
||||
UPDATED_REL_URL: "http://www.mozilla.com/firefox/sync/updated.html",
|
||||
|
|
|
@ -337,7 +337,7 @@ SyncEngine.prototype = {
|
|||
|
||||
// Create a new record using the store and add in crypto fields
|
||||
_createRecord: function SyncEngine__createRecord(id) {
|
||||
let record = this._store.createRecord(id);
|
||||
let record = this._store.createRecord(id, this.engineURL + "/" + id);
|
||||
record.id = id;
|
||||
record.encryption = this.cryptoMetaURL;
|
||||
return record;
|
||||
|
|
|
@ -756,11 +756,11 @@ BookmarksStore.prototype = {
|
|||
},
|
||||
|
||||
// Create a record starting from the weave id (places guid)
|
||||
createRecord: function createRecord(guid) {
|
||||
createRecord: function createRecord(guid, uri) {
|
||||
let placeId = idForGUID(guid);
|
||||
let record;
|
||||
if (placeId <= 0) { // deleted item
|
||||
record = new PlacesItem();
|
||||
record = new PlacesItem(uri);
|
||||
record.deleted = true;
|
||||
return record;
|
||||
}
|
||||
|
@ -770,14 +770,14 @@ BookmarksStore.prototype = {
|
|||
case this._bms.TYPE_BOOKMARK:
|
||||
let bmkUri = this._bms.getBookmarkURI(placeId).spec;
|
||||
if (this._ms && this._ms.hasMicrosummary(placeId)) {
|
||||
record = new BookmarkMicsum();
|
||||
record = new BookmarkMicsum(uri);
|
||||
let micsum = this._ms.getMicrosummary(placeId);
|
||||
record.generatorUri = micsum.generator.uri.spec; // breaks local generators
|
||||
record.staticTitle = this._getStaticTitle(placeId);
|
||||
}
|
||||
else {
|
||||
if (bmkUri.search(/^place:/) == 0) {
|
||||
record = new BookmarkQuery();
|
||||
record = new BookmarkQuery(uri);
|
||||
|
||||
// Get the actual tag name instead of the local itemId
|
||||
let folder = bmkUri.match(/[:&]folder=(\d+)/);
|
||||
|
@ -792,7 +792,7 @@ BookmarksStore.prototype = {
|
|||
catch(ex) {}
|
||||
}
|
||||
else
|
||||
record = new Bookmark();
|
||||
record = new Bookmark(uri);
|
||||
record.title = this._bms.getItemTitle(placeId);
|
||||
}
|
||||
|
||||
|
@ -806,7 +806,7 @@ BookmarksStore.prototype = {
|
|||
|
||||
case this._bms.TYPE_FOLDER:
|
||||
if (this._ls.isLivemark(placeId)) {
|
||||
record = new Livemark();
|
||||
record = new Livemark(uri);
|
||||
|
||||
let siteURI = this._ls.getSiteURI(placeId);
|
||||
if (siteURI != null)
|
||||
|
@ -814,7 +814,7 @@ BookmarksStore.prototype = {
|
|||
record.feedUri = this._ls.getFeedURI(placeId).spec;
|
||||
|
||||
} else {
|
||||
record = new BookmarkFolder();
|
||||
record = new BookmarkFolder(uri);
|
||||
}
|
||||
|
||||
record.parentName = Svc.Bookmark.getItemTitle(parent);
|
||||
|
@ -823,19 +823,19 @@ BookmarksStore.prototype = {
|
|||
break;
|
||||
|
||||
case this._bms.TYPE_SEPARATOR:
|
||||
record = new BookmarkSeparator();
|
||||
record = new BookmarkSeparator(uri);
|
||||
// Create a positioning identifier for the separator
|
||||
record.parentName = Svc.Bookmark.getItemTitle(parent);
|
||||
record.pos = Svc.Bookmark.getItemIndex(placeId);
|
||||
break;
|
||||
|
||||
case this._bms.TYPE_DYNAMIC_CONTAINER:
|
||||
record = new PlacesItem();
|
||||
record = new PlacesItem(uri);
|
||||
this._log.warn("Don't know how to serialize dynamic containers yet");
|
||||
break;
|
||||
|
||||
default:
|
||||
record = new PlacesItem();
|
||||
record = new PlacesItem(uri);
|
||||
this._log.warn("Unknown item type, cannot serialize: " +
|
||||
this._bms.getItemType(placeId));
|
||||
}
|
||||
|
|
|
@ -180,8 +180,8 @@ ClientStore.prototype = {
|
|||
this._remoteClients[record.id] = record.cleartext;
|
||||
},
|
||||
|
||||
createRecord: function createRecord(guid) {
|
||||
let record = new ClientsRec();
|
||||
createRecord: function createRecord(guid, uri) {
|
||||
let record = new ClientsRec(uri);
|
||||
|
||||
// Package the individual components into a record for the local client
|
||||
if (guid == Clients.localID) {
|
||||
|
|
|
@ -163,8 +163,8 @@ FormStore.prototype = {
|
|||
return FormWrapper.hasGUID(id);
|
||||
},
|
||||
|
||||
createRecord: function createRecord(guid) {
|
||||
let record = new FormRec();
|
||||
createRecord: function createRecord(guid, uri) {
|
||||
let record = new FormRec(uri);
|
||||
let entry = FormWrapper.getEntry(guid);
|
||||
if (entry != null) {
|
||||
record.name = entry.name;
|
||||
|
|
|
@ -279,9 +279,9 @@ HistoryStore.prototype = {
|
|||
return url ? this._hsvc.isVisited(url) : false;
|
||||
},
|
||||
|
||||
createRecord: function createRecord(guid) {
|
||||
createRecord: function createRecord(guid, uri) {
|
||||
let foo = this._findURLByGUID(guid);
|
||||
let record = new HistoryRec();
|
||||
let record = new HistoryRec(uri);
|
||||
if (foo) {
|
||||
record.histUri = foo.url;
|
||||
record.title = foo.title;
|
||||
|
|
|
@ -169,8 +169,8 @@ PasswordStore.prototype = {
|
|||
return false;
|
||||
},
|
||||
|
||||
createRecord: function createRecord(guid) {
|
||||
let record = new LoginRec();
|
||||
createRecord: function createRecord(guid, uri) {
|
||||
let record = new LoginRec(uri);
|
||||
let login = this._getLoginFromGUID(guid);
|
||||
|
||||
if (login) {
|
||||
|
|
|
@ -199,8 +199,8 @@ PrefStore.prototype = {
|
|||
return (id === WEAVE_PREFS_GUID);
|
||||
},
|
||||
|
||||
createRecord: function createRecord(guid) {
|
||||
let record = new PrefRec();
|
||||
createRecord: function createRecord(guid, uri) {
|
||||
let record = new PrefRec(uri);
|
||||
|
||||
if (guid == WEAVE_PREFS_GUID) {
|
||||
record.value = this._getAllPrefs();
|
||||
|
|
|
@ -146,8 +146,8 @@ TabStore.prototype = {
|
|||
return allTabs;
|
||||
},
|
||||
|
||||
createRecord: function createRecord(guid) {
|
||||
let record = new TabSetRecord();
|
||||
createRecord: function createRecord(guid, uri) {
|
||||
let record = new TabSetRecord(uri);
|
||||
record.clientName = Clients.localName;
|
||||
|
||||
// Don't provide any tabs to compare against and ignore the update later.
|
||||
|
|
|
@ -86,7 +86,7 @@ Store.prototype = {
|
|||
throw "override itemExists in a subclass";
|
||||
},
|
||||
|
||||
createRecord: function Store_createRecord(id) {
|
||||
createRecord: function Store_createRecord(id, uri) {
|
||||
throw "override createRecord in a subclass";
|
||||
},
|
||||
|
||||
|
|
|
@ -830,6 +830,69 @@ let Utils = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Generate 20 random characters a-z
|
||||
*/
|
||||
generatePassphrase: function() {
|
||||
let rng = Cc["@mozilla.org/security/random-generator;1"]
|
||||
.createInstance(Ci.nsIRandomGenerator);
|
||||
let bytes = rng.generateRandomBytes(20);
|
||||
return [String.fromCharCode(97 + Math.floor(byte * 26 / 256))
|
||||
for each (byte in bytes)].join("");
|
||||
},
|
||||
|
||||
/**
|
||||
* Hyphenate a 20 character passphrase in 4 groups of 5.
|
||||
*/
|
||||
hyphenatePassphrase: function(passphrase) {
|
||||
return passphrase.slice(0, 5) + '-'
|
||||
+ passphrase.slice(5, 10) + '-'
|
||||
+ passphrase.slice(10, 15) + '-'
|
||||
+ passphrase.slice(15, 20);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove hyphens as inserted by hyphenatePassphrase().
|
||||
*/
|
||||
normalizePassphrase: function(pp) {
|
||||
if (pp.length == 23 && pp[5] == '-' && pp[11] == '-' && pp[17] == '-')
|
||||
return pp.slice(0, 5) + pp.slice(6, 11)
|
||||
+ pp.slice(12, 17) + pp.slice(18, 23);
|
||||
return pp;
|
||||
},
|
||||
|
||||
/*
|
||||
* Calculate the strength of a passphrase provided by the user
|
||||
* according to the NIST algorithm (NIST 800-63 Appendix A.1).
|
||||
*/
|
||||
passphraseStrength: function passphraseStrength(value) {
|
||||
let bits = 0;
|
||||
|
||||
// The entropy of the first character is taken to be 4 bits.
|
||||
if (value.length)
|
||||
bits = 4;
|
||||
|
||||
// The entropy of the next 7 characters are 2 bits per character.
|
||||
if (value.length > 1)
|
||||
bits += Math.min(value.length - 1, 7) * 2;
|
||||
|
||||
// For the 9th through the 20th character the entropy is taken to
|
||||
// be 1.5 bits per character.
|
||||
if (value.length > 8)
|
||||
bits += Math.min(value.length - 8, 12) * 1.5;
|
||||
|
||||
// For characters 21 and above the entropy is taken to be 1 bit per character.
|
||||
if (value.length > 20)
|
||||
bits += value.length - 20;
|
||||
|
||||
// Bonus of 6 bits if we find non-alphabetic characters
|
||||
if ([char.charCodeAt() for each (char in value.toLowerCase())]
|
||||
.some(function(chr) chr < 97 || chr > 122))
|
||||
bits += 6;
|
||||
|
||||
return bits;
|
||||
},
|
||||
|
||||
/**
|
||||
* Create an array like the first but without elements of the second
|
||||
*/
|
||||
|
|
|
@ -4,6 +4,8 @@ pref("services.sync.userURL", "user/");
|
|||
pref("services.sync.miscURL", "misc/");
|
||||
pref("services.sync.termsURL", "https://services.mozilla.com/tos/");
|
||||
pref("services.sync.privacyURL", "https://services.mozilla.com/privacy-policy/");
|
||||
pref("services.sync.statusURL", "https://services.mozilla.com/status/");
|
||||
pref("services.sync.syncKeyHelpURL", "https://services.mozilla.com/help/synckey");
|
||||
|
||||
pref("services.sync.lastversion", "firstrun");
|
||||
pref("services.sync.autoconnect", true);
|
||||
|
|
|
@ -45,7 +45,7 @@ function run_test() {
|
|||
check([]);
|
||||
|
||||
function $B(name, parent, pred) {
|
||||
let bookmark = new Bookmark();
|
||||
let bookmark = new Bookmark("http://weave.server/my-bookmark");
|
||||
bookmark.id = name;
|
||||
bookmark.title = name;
|
||||
bookmark.bmkUri = "http://uri/";
|
||||
|
@ -56,7 +56,7 @@ function run_test() {
|
|||
}
|
||||
|
||||
function $F(name, parent, pred) {
|
||||
let folder = new BookmarkFolder();
|
||||
let folder = new BookmarkFolder("http://weave.server/my-bookmark-folder");
|
||||
folder.id = name;
|
||||
folder.title = name;
|
||||
folder.parentid = parent || "unfiled";
|
||||
|
|
|
@ -3,6 +3,8 @@ Cu.import("resource://services-sync/engines/bookmarks.js");
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
let baseuri = "http://fake/uri/";
|
||||
|
||||
_("Starting with a clean slate of no bookmarks");
|
||||
let store = new (new BookmarksEngine())._storeObj();
|
||||
store.wipe();
|
||||
|
@ -21,11 +23,11 @@ function run_test() {
|
|||
let second = insert(10);
|
||||
|
||||
_("Making sure the record created for the first has no predecessor");
|
||||
let pos5 = store.createRecord("pos5");
|
||||
let pos5 = store.createRecord("pos5", baseuri + "pos5");
|
||||
do_check_eq(pos5.predecessorid, undefined);
|
||||
|
||||
_("Making sure the second record has the first as its predecessor");
|
||||
let pos10 = store.createRecord("pos10");
|
||||
let pos10 = store.createRecord("pos10", baseuri + "pos10");
|
||||
do_check_eq(pos10.predecessorid, "pos5");
|
||||
|
||||
_("Make sure the index of item gets fixed");
|
||||
|
@ -35,6 +37,8 @@ function run_test() {
|
|||
_("Make sure things that are in unsorted don't set the predecessor");
|
||||
insert(0, Svc.Bookmark.unfiledBookmarksFolder);
|
||||
insert(1, Svc.Bookmark.unfiledBookmarksFolder);
|
||||
do_check_eq(store.createRecord("pos0").predecessorid, undefined);
|
||||
do_check_eq(store.createRecord("pos1").predecessorid, undefined);
|
||||
do_check_eq(store.createRecord("pos0", baseuri + "pos0").predecessorid,
|
||||
undefined);
|
||||
do_check_eq(store.createRecord("pos1", baseuri + "pos1").predecessorid,
|
||||
undefined);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ function run_test() {
|
|||
do_check_eq(Svc.Bookmark.getKeywordForBookmark(id), fxrecord.keyword);
|
||||
|
||||
_("Have the store create a new record object. Verify that it has the same data.");
|
||||
let newrecord = store.createRecord(fxrecord.id);
|
||||
let newrecord = store.createRecord(fxrecord.id, "http://fake/uri");
|
||||
for each (let property in ["type", "bmkUri", "title", "keyword",
|
||||
"parentName", "parentid"])
|
||||
do_check_eq(newrecord[property], fxrecord[property]);
|
||||
|
|
|
@ -1,58 +1,65 @@
|
|||
Cu.import("resource://services-sync/base_records/crypto.js");
|
||||
Cu.import("resource://services-sync/base_records/keys.js");
|
||||
Cu.import("resource://services-sync/engines/clients.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/identity.js");
|
||||
|
||||
function run_test() {
|
||||
let baseUri = "http://fakebase/";
|
||||
let pubUri = baseUri + "pubkey";
|
||||
let privUri = baseUri + "privkey";
|
||||
let cryptoUri = baseUri + "crypto";
|
||||
_("Set up test fixtures.");
|
||||
ID.set('WeaveID', new Identity('Some Identity', 'foo'));
|
||||
Svc.Prefs.set("clusterURL", "http://fakebase/");
|
||||
let baseUri = "http://fakebase/1.0/foo/storage/";
|
||||
let pubUri = baseUri + "keys/pubkey";
|
||||
let privUri = baseUri + "keys/privkey";
|
||||
|
||||
let passphrase = ID.set("WeaveCryptoID", new Identity());
|
||||
passphrase.password = "passphrase";
|
||||
|
||||
_("Setting up fake pub/priv keypair and symkey for encrypt/decrypt");
|
||||
PubKeys.defaultKeyUri = baseUri + "pubkey";
|
||||
PubKeys.defaultKeyUri = baseUri + "keys/pubkey";
|
||||
let {pubkey, privkey} = PubKeys.createKeypair(passphrase, pubUri, privUri);
|
||||
PubKeys.set(pubUri, pubkey);
|
||||
PrivKeys.set(privUri, privkey);
|
||||
let cryptoMeta = new CryptoMeta(cryptoUri);
|
||||
|
||||
let cryptoMeta = new CryptoMeta(Clients.cryptoMetaURL);
|
||||
cryptoMeta.addUnwrappedKey(pubkey, Svc.Crypto.generateRandomKey());
|
||||
CryptoMetas.set(cryptoUri, cryptoMeta);
|
||||
CryptoMetas.set(Clients.cryptoMetaURL, cryptoMeta);
|
||||
|
||||
_("Test that serializing client records results in uploadable ascii");
|
||||
Clients.__defineGetter__("cryptoMetaURL", function() cryptoUri);
|
||||
Clients.localID = "ascii";
|
||||
Clients.localName = "wéävê";
|
||||
try {
|
||||
_("Test that serializing client records results in uploadable ascii");
|
||||
Clients.localID = "ascii";
|
||||
Clients.localName = "wéävê";
|
||||
|
||||
_("Make sure we have the expected record");
|
||||
let record = Clients._createRecord("ascii");
|
||||
do_check_eq(record.id, "ascii");
|
||||
do_check_eq(record.name, "wéävê");
|
||||
_("Make sure we have the expected record");
|
||||
let record = Clients._createRecord("ascii");
|
||||
do_check_eq(record.id, "ascii");
|
||||
do_check_eq(record.name, "wéävê");
|
||||
|
||||
record.encrypt(passphrase)
|
||||
let serialized = JSON.stringify(record);
|
||||
let checkCount = 0;
|
||||
_("Checking for all ASCII:", serialized);
|
||||
Array.forEach(serialized, function(ch) {
|
||||
let code = ch.charCodeAt(0);
|
||||
_("Checking asciiness of '", ch, "'=", code);
|
||||
do_check_true(code < 128);
|
||||
checkCount++;
|
||||
});
|
||||
record.encrypt(passphrase);
|
||||
let serialized = JSON.stringify(record);
|
||||
let checkCount = 0;
|
||||
_("Checking for all ASCII:", serialized);
|
||||
Array.forEach(serialized, function(ch) {
|
||||
let code = ch.charCodeAt(0);
|
||||
_("Checking asciiness of '", ch, "'=", code);
|
||||
do_check_true(code < 128);
|
||||
checkCount++;
|
||||
});
|
||||
|
||||
_("Processed", checkCount, "characters out of", serialized.length);
|
||||
do_check_eq(checkCount, serialized.length);
|
||||
_("Processed", checkCount, "characters out of", serialized.length);
|
||||
do_check_eq(checkCount, serialized.length);
|
||||
|
||||
_("Making sure the record still looks like it did before");
|
||||
record.decrypt(passphrase)
|
||||
do_check_eq(record.id, "ascii");
|
||||
do_check_eq(record.name, "wéävê");
|
||||
_("Making sure the record still looks like it did before");
|
||||
record.decrypt(passphrase);
|
||||
do_check_eq(record.id, "ascii");
|
||||
do_check_eq(record.name, "wéävê");
|
||||
|
||||
_("Sanity check that creating the record also gives the same");
|
||||
record = Clients._createRecord("ascii");
|
||||
do_check_eq(record.id, "ascii");
|
||||
do_check_eq(record.name, "wéävê");
|
||||
_("Sanity check that creating the record also gives the same");
|
||||
record = Clients._createRecord("ascii");
|
||||
do_check_eq(record.id, "ascii");
|
||||
do_check_eq(record.name, "wéävê");
|
||||
} finally {
|
||||
Svc.Prefs.resetBranch("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,17 +3,19 @@ Cu.import("resource://services-sync/base_records/collection.js");
|
|||
Cu.import("resource://services-sync/base_records/wbo.js");
|
||||
|
||||
function run_test() {
|
||||
let coll = new Collection("", WBORecord);
|
||||
let coll = new Collection("http://fake/uri", WBORecord);
|
||||
let stream = { _data: "" };
|
||||
let called, recCount, sum;
|
||||
|
||||
_("Not-JSON, string payloads are strings");
|
||||
called = false;
|
||||
stream._data = '{"payload":"hello"}\n';
|
||||
stream._data = '{"id":"hello","payload":"world"}\n';
|
||||
coll.recordHandler = function(rec) {
|
||||
called = true;
|
||||
_("Got record:", JSON.stringify(rec));
|
||||
do_check_eq(rec.payload, "hello");
|
||||
do_check_eq(rec.id, "hello");
|
||||
do_check_eq(rec.uri.spec, "http://fake/uri/hello");
|
||||
do_check_eq(rec.payload, "world");
|
||||
};
|
||||
coll._onProgress.call(stream);
|
||||
do_check_eq(stream._data, '');
|
||||
|
@ -39,7 +41,7 @@ function run_test() {
|
|||
called = false;
|
||||
recCount = 0;
|
||||
sum = 0;
|
||||
stream._data = '{"payload":"{\\"value\\":100}"}\n{"payload":"{\\"value\\":10}"}\n{"payload":"{\\"value\\":1}"}\n';
|
||||
stream._data = '{"id":"hundred","payload":"{\\"value\\":100}"}\n{"id":"ten","payload":"{\\"value\\":10}"}\n{"id":"one","payload":"{\\"value\\":1}"}\n';
|
||||
coll.recordHandler = function(rec) {
|
||||
called = true;
|
||||
_("Got record:", JSON.stringify(rec));
|
||||
|
@ -48,14 +50,20 @@ function run_test() {
|
|||
_("Incremental status: count", recCount, "sum", sum);
|
||||
switch (recCount) {
|
||||
case 1:
|
||||
do_check_eq(rec.id, "hundred");
|
||||
do_check_eq(rec.uri.spec, "http://fake/uri/hundred");
|
||||
do_check_eq(rec.payload.value, 100);
|
||||
do_check_eq(sum, 100);
|
||||
break;
|
||||
case 2:
|
||||
do_check_eq(rec.id, "ten");
|
||||
do_check_eq(rec.uri.spec, "http://fake/uri/ten");
|
||||
do_check_eq(rec.payload.value, 10);
|
||||
do_check_eq(sum, 110);
|
||||
break;
|
||||
case 3:
|
||||
do_check_eq(rec.id, "one");
|
||||
do_check_eq(rec.uri.spec, "http://fake/uri/one");
|
||||
do_check_eq(rec.payload.value, 1);
|
||||
do_check_eq(sum, 111);
|
||||
break;
|
||||
|
|
|
@ -3,6 +3,7 @@ Cu.import("resource://services-sync/engines/forms.js");
|
|||
Cu.import("resource://services-sync/type_records/forms.js");
|
||||
|
||||
function run_test() {
|
||||
let baseuri = "http://fake/uri/";
|
||||
let store = new FormEngine()._store;
|
||||
|
||||
_("Remove any existing entries");
|
||||
|
@ -27,13 +28,13 @@ function run_test() {
|
|||
}
|
||||
do_check_true(store.itemExists(id));
|
||||
|
||||
let rec = store.createRecord(id);
|
||||
let rec = store.createRecord(id, baseuri + id);
|
||||
_("Got record for id", id, rec);
|
||||
do_check_eq(rec.name, "name!!");
|
||||
do_check_eq(rec.value, "value??");
|
||||
|
||||
_("Create a non-existant id for delete");
|
||||
do_check_true(store.createRecord("deleted!!").deleted);
|
||||
_("Create a non-existent id for delete");
|
||||
do_check_true(store.createRecord("deleted!!", baseuri + "deleted!!").deleted);
|
||||
|
||||
_("Try updating.. doesn't do anything yet");
|
||||
store.update({});
|
||||
|
|
|
@ -71,11 +71,11 @@ function run_test() {
|
|||
do_check_true(store.itemExists(fxguid));
|
||||
|
||||
_("If we query a non-existent record, it's marked as deleted.");
|
||||
let record = store.createRecord("non-existent");
|
||||
let record = store.createRecord("non-existent", "http://fake/uri");
|
||||
do_check_true(record.deleted);
|
||||
|
||||
_("Verify createRecord() returns a complete record.");
|
||||
record = store.createRecord(fxguid);
|
||||
record = store.createRecord(fxguid, "http://fake/urk");
|
||||
do_check_eq(record.histUri, fxuri.spec);
|
||||
do_check_eq(record.title, "Get Firefox!");
|
||||
do_check_eq(record.visits.length, 1);
|
||||
|
|
|
@ -8,28 +8,28 @@ Cu.import("resource://services-sync/util.js");
|
|||
let keys, cryptoMeta, cryptoWrap;
|
||||
|
||||
function pubkey_handler(metadata, response) {
|
||||
let obj = {id: "ignore-me",
|
||||
let obj = {id: "pubkey",
|
||||
modified: keys.pubkey.modified,
|
||||
payload: JSON.stringify(keys.pubkey.payload)};
|
||||
return httpd_basic_auth_handler(JSON.stringify(obj), metadata, response);
|
||||
}
|
||||
|
||||
function privkey_handler(metadata, response) {
|
||||
let obj = {id: "ignore-me-2",
|
||||
let obj = {id: "privkey",
|
||||
modified: keys.privkey.modified,
|
||||
payload: JSON.stringify(keys.privkey.payload)};
|
||||
return httpd_basic_auth_handler(JSON.stringify(obj), metadata, response);
|
||||
}
|
||||
|
||||
function crypted_resource_handler(metadata, response) {
|
||||
let obj = {id: "ignore-me-3",
|
||||
let obj = {id: "resource",
|
||||
modified: cryptoWrap.modified,
|
||||
payload: JSON.stringify(cryptoWrap.payload)};
|
||||
return httpd_basic_auth_handler(JSON.stringify(obj), metadata, response);
|
||||
}
|
||||
|
||||
function crypto_meta_handler(metadata, response) {
|
||||
let obj = {id: "ignore-me-4",
|
||||
let obj = {id: "steam",
|
||||
modified: cryptoMeta.modified,
|
||||
payload: JSON.stringify(cryptoMeta.payload)};
|
||||
return httpd_basic_auth_handler(JSON.stringify(obj), metadata, response);
|
||||
|
@ -48,34 +48,39 @@ function run_test() {
|
|||
|
||||
log.info("Setting up server and authenticator");
|
||||
|
||||
server = httpd_setup({"/pubkey": pubkey_handler,
|
||||
"/privkey": privkey_handler,
|
||||
"/crypted-resource": crypted_resource_handler,
|
||||
"/crypto-meta": crypto_meta_handler});
|
||||
server = httpd_setup({"/keys/pubkey": pubkey_handler,
|
||||
"/keys/privkey": privkey_handler,
|
||||
"/steam/resource": crypted_resource_handler,
|
||||
"/crypto/steam": crypto_meta_handler});
|
||||
|
||||
let auth = new BasicAuthenticator(new Identity("secret", "guest", "guest"));
|
||||
Auth.defaultAuthenticator = auth;
|
||||
|
||||
log.info("Generating keypair + symmetric key");
|
||||
|
||||
PubKeys.defaultKeyUri = "http://localhost:8080/pubkey";
|
||||
PubKeys.defaultKeyUri = "http://localhost:8080/keys/pubkey";
|
||||
keys = PubKeys.createKeypair(passphrase,
|
||||
"http://localhost:8080/pubkey",
|
||||
"http://localhost:8080/privkey");
|
||||
"http://localhost:8080/keys/pubkey",
|
||||
"http://localhost:8080/keys/privkey");
|
||||
let crypto = Svc.Crypto;
|
||||
keys.symkey = crypto.generateRandomKey();
|
||||
keys.wrappedkey = crypto.wrapSymmetricKey(keys.symkey, keys.pubkey.keyData);
|
||||
|
||||
log.info("Setting up keyring");
|
||||
|
||||
cryptoMeta = new CryptoMeta("http://localhost:8080/crypto-meta", auth);
|
||||
cryptoMeta = new CryptoMeta("http://localhost:8080/crypto/steam", auth);
|
||||
cryptoMeta.addUnwrappedKey(keys.pubkey, keys.symkey);
|
||||
CryptoMetas.set(cryptoMeta.uri, cryptoMeta);
|
||||
|
||||
log.info("Creating and encrypting a record");
|
||||
log.info("Creating a record");
|
||||
|
||||
cryptoWrap = new CryptoWrapper("http://localhost:8080/steam/resource");
|
||||
cryptoWrap.encryption = "http://localhost:8080/crypto/steam";
|
||||
do_check_eq(cryptoWrap.encryption, "http://localhost:8080/crypto/steam");
|
||||
do_check_eq(cryptoWrap.payload.encryption, "../crypto/steam");
|
||||
|
||||
log.info("Encrypting a record");
|
||||
|
||||
cryptoWrap = new CryptoWrapper("http://localhost:8080/crypted-resource", auth);
|
||||
cryptoWrap.encryption = "http://localhost:8080/crypto-meta";
|
||||
cryptoWrap.cleartext.stuff = "my payload here";
|
||||
cryptoWrap.encrypt(passphrase);
|
||||
let firstIV = cryptoWrap.IV;
|
||||
|
@ -107,7 +112,7 @@ function run_test() {
|
|||
catch(ex) {
|
||||
error = ex;
|
||||
}
|
||||
do_check_eq(error, "Record id mismatch: crypted-resource,other");
|
||||
do_check_eq(error, "Record id mismatch: resource,other");
|
||||
|
||||
log.info("Make sure wrong hmacs cause failures");
|
||||
cryptoWrap.encrypt(passphrase);
|
||||
|
|
|
@ -30,8 +30,9 @@ function run_test() {
|
|||
crypto.addUnwrappedKey(pubkey, symkey);
|
||||
|
||||
_("Changing the HMAC to force a mismatch");
|
||||
let goodHMAC = crypto.keyring[pubkey.uri.spec].hmac;
|
||||
crypto.keyring[pubkey.uri.spec].hmac = "failme!";
|
||||
let relUri = crypto.uri.getRelativeSpec(pubkey.uri);
|
||||
let goodHMAC = crypto.keyring[relUri].hmac;
|
||||
crypto.keyring[relUri].hmac = "failme!";
|
||||
let error = "";
|
||||
try {
|
||||
crypto.getKey(privkey, passphrase);
|
||||
|
@ -42,6 +43,6 @@ function run_test() {
|
|||
do_check_eq(error, "Key SHA256 HMAC mismatch: failme!");
|
||||
|
||||
_("Switching back to the correct HMAC and trying again");
|
||||
crypto.keyring[pubkey.uri.spec].hmac = goodHMAC;
|
||||
crypto.keyring[relUri].hmac = goodHMAC;
|
||||
crypto.getKey(privkey, passphrase);
|
||||
}
|
||||
|
|
|
@ -52,8 +52,25 @@ function test_createKeypair() {
|
|||
let id = ID.set('foo', new Identity('foo', 'luser'));
|
||||
id.password = passphrase;
|
||||
|
||||
_("Key pair requires URIs for both keys.");
|
||||
let error;
|
||||
try {
|
||||
let result = PubKeys.createKeypair(id);
|
||||
} catch(ex) {
|
||||
error = ex;
|
||||
}
|
||||
do_check_eq(error, "Missing or null parameter 'pubkeyUri'.");
|
||||
|
||||
error = undefined;
|
||||
try {
|
||||
let result = PubKeys.createKeypair(id, "http://host/pub/key");
|
||||
} catch(ex) {
|
||||
error = ex;
|
||||
}
|
||||
do_check_eq(error, "Missing or null parameter 'privkeyUri'.");
|
||||
|
||||
_("Generate a key pair.");
|
||||
let result = PubKeys.createKeypair(id, "http://pub/key", "http://priv/key");
|
||||
let result = PubKeys.createKeypair(id, "http://host/pub/key", "http://host/priv/key");
|
||||
|
||||
_("Check that salt and IV are of correct length.");
|
||||
// 16 bytes = 24 base64 encoded characters
|
||||
|
@ -61,10 +78,13 @@ function test_createKeypair() {
|
|||
do_check_eq(result.privkey.iv.length, 24);
|
||||
|
||||
_("URIs are set.");
|
||||
do_check_eq(result.pubkey.uri.spec, "http://pub/key");
|
||||
do_check_eq(result.pubkey.privateKeyUri.spec, "http://priv/key");
|
||||
do_check_eq(result.privkey.uri.spec, "http://priv/key");
|
||||
do_check_eq(result.privkey.publicKeyUri.spec, "http://pub/key");
|
||||
do_check_eq(result.pubkey.uri.spec, "http://host/pub/key");
|
||||
do_check_eq(result.pubkey.privateKeyUri.spec, "http://host/priv/key");
|
||||
do_check_eq(result.pubkey.payload.privateKeyUri, "../priv/key");
|
||||
|
||||
do_check_eq(result.privkey.uri.spec, "http://host/priv/key");
|
||||
do_check_eq(result.privkey.publicKeyUri.spec, "http://host/pub/key");
|
||||
do_check_eq(result.privkey.payload.publicKeyUri, "../pub/key");
|
||||
|
||||
_("UTF8 encoded passphrase was used.");
|
||||
do_check_true(Svc.Crypto.verifyPassphrase(result.privkey.keyData,
|
||||
|
|
|
@ -51,7 +51,7 @@ function run_test() {
|
|||
let res = new Resource("http://localhost:8080/record");
|
||||
let resp = res.get();
|
||||
|
||||
let rec = new WBORecord();
|
||||
let rec = new WBORecord("http://localhost:8080/record");
|
||||
rec.deserialize(res.data);
|
||||
do_check_eq(rec.id, "asdf-1234-asdf-1234"); // NOT "record"!
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@ SteamStore.prototype = {
|
|||
return (id in this.items);
|
||||
},
|
||||
|
||||
createRecord: function(id) {
|
||||
var record = new SteamRecord();
|
||||
createRecord: function(id, uri) {
|
||||
var record = new SteamRecord(uri);
|
||||
record.id = id;
|
||||
record.denomination = this.items[id] || "Data for new record: " + id;
|
||||
return record;
|
||||
|
@ -257,7 +257,7 @@ function test_syncStartup_metaGet404() {
|
|||
do_check_eq(collection.wbos.scotsman.payload, undefined);
|
||||
|
||||
_("New bulk key was uploaded");
|
||||
let key = crypto_steam.data.keyring["http://localhost:8080/1.0/foo/storage/keys/pubkey"];
|
||||
let key = crypto_steam.data.keyring["../keys/pubkey"];
|
||||
do_check_eq(key.wrapped, "fake-symmetric-key-0");
|
||||
do_check_eq(key.hmac, "fake-symmetric-key-0 ");
|
||||
|
||||
|
@ -439,7 +439,7 @@ function test_syncStartup_badKeyWipesServerData() {
|
|||
do_check_eq(collection.wbos.scotsman.payload, undefined);
|
||||
|
||||
// New bulk key was uploaded
|
||||
key = crypto_steam.data.keyring["http://localhost:8080/1.0/foo/storage/keys/pubkey"];
|
||||
key = crypto_steam.data.keyring["../keys/pubkey"];
|
||||
do_check_eq(key.wrapped, "fake-symmetric-key-1");
|
||||
do_check_eq(key.hmac, "fake-symmetric-key-1 ");
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
Cu.import("resource://services-sync/engines/tabs.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function fakeSessionSvc() {
|
||||
let tabs = [];
|
||||
for(let i = 0; i < arguments.length; i++) {
|
||||
tabs.push({
|
||||
index: 1,
|
||||
entries: [{
|
||||
url: arguments[i],
|
||||
title: "title"
|
||||
}],
|
||||
attributes: {
|
||||
image: "image"
|
||||
},
|
||||
extData: {
|
||||
weaveLastUsed: 1
|
||||
}
|
||||
});
|
||||
}
|
||||
let obj = {windows: [{tabs: tabs}]};
|
||||
|
||||
// delete the getter, or the previously created fake Session
|
||||
delete Svc.Session;
|
||||
Svc.Session = {
|
||||
getBrowserState: function() JSON.stringify(obj)
|
||||
};
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
|
||||
_("test locallyOpenTabMatchesURL");
|
||||
let engine = new TabEngine();
|
||||
|
||||
// 3 tabs
|
||||
fakeSessionSvc("http://bar.com", "http://foo.com", "http://foobar.com");
|
||||
|
||||
let matches;
|
||||
|
||||
_(" test matching works (true)");
|
||||
matches = engine.locallyOpenTabMatchesURL("http://foo.com");
|
||||
do_check_true(matches);
|
||||
|
||||
_(" test matching works (false)");
|
||||
matches = engine.locallyOpenTabMatchesURL("http://barfoo.com");
|
||||
do_check_false(matches);
|
||||
}
|
|
@ -0,0 +1,119 @@
|
|||
Cu.import("resource://services-sync/engines/tabs.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/type_records/tabs.js");
|
||||
|
||||
function test_create() {
|
||||
let store = new TabEngine()._store;
|
||||
|
||||
_("Create a first record");
|
||||
let rec = {id: "id1",
|
||||
clientName: "clientName1",
|
||||
cleartext: "cleartext1",
|
||||
modified: 1000};
|
||||
store.applyIncoming(rec);
|
||||
do_check_eq(store._remoteClients["id1"], "cleartext1");
|
||||
do_check_eq(Svc.Prefs.get("notifyTabState"), 1);
|
||||
|
||||
_("Create a second record");
|
||||
let rec = {id: "id2",
|
||||
clientName: "clientName2",
|
||||
cleartext: "cleartext2",
|
||||
modified: 2000};
|
||||
store.applyIncoming(rec);
|
||||
do_check_eq(store._remoteClients["id2"], "cleartext2");
|
||||
do_check_eq(Svc.Prefs.get("notifyTabState"), 0);
|
||||
|
||||
_("Create a third record");
|
||||
let rec = {id: "id3",
|
||||
clientName: "clientName3",
|
||||
cleartext: "cleartext3",
|
||||
modified: 3000};
|
||||
store.applyIncoming(rec);
|
||||
do_check_eq(store._remoteClients["id3"], "cleartext3");
|
||||
do_check_eq(Svc.Prefs.get("notifyTabState"), 0);
|
||||
|
||||
// reset the notifyTabState
|
||||
Svc.Prefs.reset("notifyTabState");
|
||||
}
|
||||
|
||||
function fakeSessionSvc(url, numtabs) {
|
||||
// first delete the getter, or the previously
|
||||
// created fake Session
|
||||
delete Svc.Session;
|
||||
Svc.Session = {
|
||||
getBrowserState: function() {
|
||||
let obj = {
|
||||
windows: [{
|
||||
tabs: [{
|
||||
index: 1,
|
||||
entries: [{
|
||||
url: url,
|
||||
title: "title"
|
||||
}],
|
||||
attributes: {
|
||||
image: "image"
|
||||
},
|
||||
extData: {
|
||||
weaveLastUsed: 1
|
||||
}
|
||||
}]
|
||||
}]
|
||||
};
|
||||
if (numtabs) {
|
||||
let tabs = obj.windows[0].tabs;
|
||||
for (let i = 0; i < numtabs-1; i++)
|
||||
tabs.push(Utils.deepCopy(tabs[0]));
|
||||
}
|
||||
return JSON.stringify(obj);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function test_getAllTabs() {
|
||||
let store = new TabEngine()._store, tabs;
|
||||
|
||||
_("get all tabs");
|
||||
fakeSessionSvc("http://foo.com");
|
||||
tabs = store.getAllTabs();
|
||||
do_check_eq(tabs.length, 1);
|
||||
do_check_eq(tabs[0].title, "title");
|
||||
do_check_eq(tabs[0].urlHistory.length, 1);
|
||||
do_check_eq(tabs[0].urlHistory[0], ["http://foo.com"]);
|
||||
do_check_eq(tabs[0].icon, "image");
|
||||
do_check_eq(tabs[0].lastUsed, 1);
|
||||
|
||||
_("get all tabs, and check that filtering works");
|
||||
// we don't bother testing every URL type here, the
|
||||
// filteredUrls regex really should have it own tests
|
||||
fakeSessionSvc("about:foo");
|
||||
tabs = store.getAllTabs(true);
|
||||
do_check_eq(tabs.length, 0);
|
||||
}
|
||||
|
||||
function test_createRecord() {
|
||||
let store = new TabEngine()._store, record;
|
||||
|
||||
// get some values before testing
|
||||
fakeSessionSvc("http://foo.com");
|
||||
let tabs = store.getAllTabs();
|
||||
let tabsize = JSON.stringify(tabs[0]).length;
|
||||
let numtabs = Math.ceil(20000./77.);
|
||||
|
||||
_("create a record");
|
||||
fakeSessionSvc("http://foo.com");
|
||||
record = store.createRecord("fake-guid", "http://fake.uri/");
|
||||
do_check_true(record instanceof TabSetRecord);
|
||||
do_check_eq(record.tabs.length, 1);
|
||||
|
||||
_("create a big record");
|
||||
fakeSessionSvc("http://foo.com", numtabs);
|
||||
record = store.createRecord("fake-guid", "http://fake.uri/");
|
||||
do_check_true(record instanceof TabSetRecord);
|
||||
do_check_eq(record.tabs.length, 256);
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
test_create();
|
||||
test_getAllTabs();
|
||||
test_createRecord();
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
Cu.import("resource://services-sync/engines/tabs.js");
|
||||
Cu.import("resource://services-sync/engines/clients.js");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function fakeSvcWinMediator() {
|
||||
// actions on windows are captured in logs
|
||||
let logs = [];
|
||||
delete Svc.WinMediator;
|
||||
Svc.WinMediator = {
|
||||
getEnumerator: function() {
|
||||
return {
|
||||
cnt: 2,
|
||||
hasMoreElements: function() this.cnt-- > 0,
|
||||
getNext: function() {
|
||||
let elt = {addTopics: [], remTopics: []};
|
||||
logs.push(elt);
|
||||
return {
|
||||
addEventListener: function(topic) {
|
||||
elt.addTopics.push(topic);
|
||||
},
|
||||
removeEventListener: function(topic) {
|
||||
elt.remTopics.push(topic);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
return logs;
|
||||
}
|
||||
|
||||
function fakeSvcSession() {
|
||||
// actions on Session are captured in logs
|
||||
let logs = [];
|
||||
delete Svc.Session;
|
||||
Svc.Session = {
|
||||
setTabValue: function(target, prop, value) {
|
||||
logs.push({target: target, prop: prop, value: value});
|
||||
}
|
||||
};
|
||||
return logs;
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
let engine = new TabEngine();
|
||||
engine._store.wipe();
|
||||
|
||||
_("Verify we have an empty tracker to work with");
|
||||
let tracker = engine._tracker;
|
||||
do_check_eq([id for (id in tracker.changedIDs)].length, 0);
|
||||
|
||||
let logs;
|
||||
|
||||
_("Test listeners are registered on windows");
|
||||
logs = fakeSvcWinMediator();
|
||||
Svc.Obs.notify("weave:engine:start-tracking");
|
||||
do_check_eq(logs.length, 2);
|
||||
for each (let log in logs) {
|
||||
do_check_eq(log.addTopics.length, 5);
|
||||
do_check_true(log.addTopics.indexOf("pageshow") >= 0);
|
||||
do_check_true(log.addTopics.indexOf("TabOpen") >= 0);
|
||||
do_check_true(log.addTopics.indexOf("TabClose") >= 0);
|
||||
do_check_true(log.addTopics.indexOf("TabSelect") >= 0);
|
||||
do_check_true(log.addTopics.indexOf("unload") >= 0);
|
||||
do_check_eq(log.remTopics.length, 0);
|
||||
}
|
||||
|
||||
_("Test listeners are unregistered on windows");
|
||||
logs = fakeSvcWinMediator();
|
||||
Svc.Obs.notify("weave:engine:stop-tracking");
|
||||
do_check_eq(logs.length, 2);
|
||||
for each (let log in logs) {
|
||||
do_check_eq(log.addTopics.length, 0);
|
||||
do_check_eq(log.remTopics.length, 5);
|
||||
do_check_true(log.remTopics.indexOf("pageshow") >= 0);
|
||||
do_check_true(log.remTopics.indexOf("TabOpen") >= 0);
|
||||
do_check_true(log.remTopics.indexOf("TabClose") >= 0);
|
||||
do_check_true(log.remTopics.indexOf("TabSelect") >= 0);
|
||||
do_check_true(log.remTopics.indexOf("unload") >= 0);
|
||||
}
|
||||
|
||||
_("Test tab listener");
|
||||
logs = fakeSvcSession();
|
||||
let idx = 0;
|
||||
for each (let evttype in ["TabOpen", "TabClose", "TabSelect"]) {
|
||||
tracker.onTab({type: evttype , originalTarget: evttype});
|
||||
do_check_eq([id for (id in tracker.changedIDs)].length, 1);
|
||||
do_check_eq(logs.length, idx+1);
|
||||
do_check_eq(logs[idx].target, evttype);
|
||||
do_check_eq(logs[idx].prop, "weaveLastUsed");
|
||||
do_check_true(typeof logs[idx].value == "number");
|
||||
idx++;
|
||||
}
|
||||
tracker.onTab({type: "pageshow", originalTarget: "pageshow"});
|
||||
do_check_eq([id for (id in tracker.changedIDs)].length, 1);
|
||||
do_check_eq(logs.length, idx); // test that setTabValue isn't called
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
let thing = {o: {foo: "foo", bar: ["bar"]}, a: ["foo", {bar: "bar"}]};
|
||||
let ret = Utils.deepCopy(thing);
|
||||
do_check_neq(ret, thing)
|
||||
do_check_neq(ret.o, thing.o);
|
||||
do_check_neq(ret.o.bar, thing.o.bar);
|
||||
do_check_neq(ret.a, thing.a);
|
||||
do_check_neq(ret.a[1], thing.a[1]);
|
||||
do_check_eq(ret.o.foo, thing.o.foo);
|
||||
do_check_eq(ret.o.bar[0], thing.o.bar[0]);
|
||||
do_check_eq(ret.a[0], thing.a[0]);
|
||||
do_check_eq(ret.a[1].bar, thing.a[1].bar);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function WinMock(href) {
|
||||
this.location = {href: href};
|
||||
this._open = true;
|
||||
};
|
||||
WinMock.prototype = {
|
||||
addEventListener: function(type, listener) {
|
||||
this._listener = listener;
|
||||
},
|
||||
close: function() {
|
||||
if (this._listener) {
|
||||
this._listener();
|
||||
}
|
||||
this._open = false;
|
||||
}
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
let w1 = new WinMock("chrome://win/win.xul");
|
||||
Utils.ensureOneOpen(w1);
|
||||
do_check_true(w1._open);
|
||||
|
||||
let w2 = new WinMock("chrome://win/win.xul");
|
||||
Utils.ensureOneOpen(w2);
|
||||
do_check_false(w1._open);
|
||||
|
||||
// close w2 and test that ensureOneOpen doesn't
|
||||
// close it again
|
||||
w2.close();
|
||||
w2._open = true;
|
||||
let w3 = new WinMock("chrome://win/win.xul");
|
||||
Utils.ensureOneOpen(w3);
|
||||
do_check_true(w2._open);
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
_("Test file-related utility functions");
|
||||
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/constants.js");
|
||||
|
||||
function run_test() {
|
||||
_test_getTmp();
|
||||
_test_open();
|
||||
}
|
||||
|
||||
function _test_getTmp() {
|
||||
// as the setup phase remove the tmp directory from the
|
||||
// filesystem
|
||||
let svc = Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(Ci.nsIProperties);
|
||||
let tmp = svc.get("ProfD", Ci.nsIFile);
|
||||
tmp.QueryInterface(Ci.nsILocalFile);
|
||||
tmp.append("weave");
|
||||
tmp.append("tmp");
|
||||
if (tmp.exists())
|
||||
tmp.remove(true);
|
||||
|
||||
// call getTmp with no argument. A ref to the tmp
|
||||
// dir is returned
|
||||
_("getTmp with no argument");
|
||||
let tmpDir = Utils.getTmp();
|
||||
do_check_true(tmpDir instanceof Ci.nsILocalFile);
|
||||
do_check_true(tmpDir.isDirectory());
|
||||
do_check_true(tmpDir.exists());
|
||||
do_check_eq(tmpDir.leafName, "tmp");
|
||||
|
||||
// call getTmp with a string. A ref to the file
|
||||
// named with this string and included in the
|
||||
// tmp dir is returned
|
||||
_("getTmp with a string");
|
||||
let tmpFile = Utils.getTmp("name");
|
||||
do_check_true(tmpFile instanceof Ci.nsILocalFile);
|
||||
do_check_true(!tmpFile.exists()); // getTmp doesn't create the file!
|
||||
do_check_eq(tmpFile.leafName, "name");
|
||||
do_check_true(tmpDir.contains(tmpFile, false));
|
||||
}
|
||||
|
||||
function _test_open() {
|
||||
|
||||
// we rely on Utils.getTmp to get a temporary file and
|
||||
// test Utils.open on that file, that's ok Util.getTmp
|
||||
// is also tested (test_getTmp)
|
||||
function createFile() {
|
||||
let f = Utils.getTmp("_test_");
|
||||
f.create(f.NORMAL_FILE_TYPE, PERMS_FILE);
|
||||
return f;
|
||||
}
|
||||
|
||||
// we should probably test more things here, for example
|
||||
// we should test that we cannot write to a stream that
|
||||
// is created as a result of opening a file for reading
|
||||
|
||||
let s, f;
|
||||
|
||||
_("Open for reading, providing a file");
|
||||
let f1 = createFile();
|
||||
[s, f] = Utils.open(f1, "<");
|
||||
do_check_eq(f.path, f1.path);
|
||||
do_check_true(s instanceof Ci.nsIConverterInputStream);
|
||||
f1.remove(false);
|
||||
|
||||
_("Open for reading, providing a file name");
|
||||
let f2 = createFile();
|
||||
let path2 = f2.path;
|
||||
[s, f] = Utils.open(path2, "<");
|
||||
do_check_eq(f.path, path2);
|
||||
do_check_true(s instanceof Ci.nsIConverterInputStream);
|
||||
f2.remove(false);
|
||||
|
||||
_("Open for writing with truncate mode, providing a file");
|
||||
let f3 = createFile();
|
||||
[s, f] = Utils.open(f3, ">");
|
||||
do_check_eq(f.path, f3.path);
|
||||
do_check_true(s instanceof Ci.nsIConverterOutputStream);
|
||||
f3.remove(false);
|
||||
|
||||
_("Open for writing with truncate mode, providing a file name");
|
||||
let f4 = createFile();
|
||||
let path4 = f4.path;
|
||||
[s, f] = Utils.open(path4, ">");
|
||||
do_check_eq(f.path, path4);
|
||||
do_check_true(s instanceof Ci.nsIConverterOutputStream);
|
||||
f4.remove(false);
|
||||
|
||||
_("Open for writing with append mode, providing a file");
|
||||
let f5 = createFile();
|
||||
[s, f] = Utils.open(f5, ">>");
|
||||
do_check_eq(f.path, f5.path);
|
||||
do_check_true(s instanceof Ci.nsIConverterOutputStream);
|
||||
f5.remove(false);
|
||||
|
||||
_("Open for writing with append mode, providing a file name");
|
||||
let f6 = createFile();
|
||||
let path6 = f6.path;
|
||||
[s, f] = Utils.open(path6, ">>");
|
||||
do_check_eq(f.path, path6);
|
||||
do_check_true(s instanceof Ci.nsIConverterOutputStream);
|
||||
f6.remove(false);
|
||||
|
||||
_("Open with illegal mode");
|
||||
let f7 = createFile();
|
||||
let except7;
|
||||
try {
|
||||
Utils.open(f7, "?!");
|
||||
} catch(e) {
|
||||
except7 = e;
|
||||
}
|
||||
do_check_true(!!except7);
|
||||
f7.remove(false);
|
||||
|
||||
_("Open non-existing file for reading");
|
||||
let f8 = createFile();
|
||||
let path8 = f8.path;
|
||||
f8.remove(false);
|
||||
let except8;
|
||||
try {
|
||||
Utils.open(path8, "<");
|
||||
} catch(e) {
|
||||
except8 = e;
|
||||
}
|
||||
do_check_true(!!except8);
|
||||
|
||||
_("Open for reading, provide permissions");
|
||||
let f9 = createFile();
|
||||
[s, f] = Utils.open(f9, "<", 0644);
|
||||
do_check_eq(f.path, f9.path);
|
||||
do_check_true(s instanceof Ci.nsIConverterInputStream);
|
||||
f9.remove(false);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
let str;
|
||||
|
||||
// we just test whether the returned string includes the
|
||||
// string "unknown", should be good enough
|
||||
|
||||
str = Utils.getErrorString("error.login.reason.password");
|
||||
do_check_true(str.match(/unknown/i) == null);
|
||||
|
||||
str = Utils.getErrorString("foobar");
|
||||
do_check_true(str.match(/unknown/i) != null);
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
_("Test with a valid icon URI");
|
||||
let iconUri = "http://foo.bar/favicon.png";
|
||||
let icon1 = Utils.getIcon(iconUri);
|
||||
do_check_true(icon1.indexOf(iconUri) > 0);
|
||||
|
||||
_("Test with an invalid icon URI and default icon");
|
||||
let icon2 = Utils.getIcon("foo", "bar");
|
||||
do_check_eq(icon2, "bar");
|
||||
|
||||
_("Test with an invalid icon URI and no default icon");
|
||||
let icon3 = Utils.getIcon("foo");
|
||||
var defaultFavicon = Cc["@mozilla.org/browser/favicon-service;1"]
|
||||
.getService(Ci.nsIFaviconService).defaultFavicon.spec;
|
||||
do_check_eq(icon3, defaultFavicon);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
let undef;
|
||||
|
||||
function run_test() {
|
||||
do_check_true(Utils.isArray([]));
|
||||
do_check_true(Utils.isArray([1, 2]));
|
||||
do_check_false(Utils.isArray({}));
|
||||
do_check_false(Utils.isArray(1.0));
|
||||
do_check_false(Utils.isArray("string"));
|
||||
do_check_false(Utils.isArray(null));
|
||||
do_check_false(Utils.isArray(undef));
|
||||
do_check_false(Utils.isArray(new Date()));
|
||||
}
|
|
@ -43,4 +43,18 @@ function run_test() {
|
|||
});
|
||||
do_check_eq(typeof num, "number");
|
||||
do_check_eq(num, 42);
|
||||
|
||||
_("Verify that things get logged");
|
||||
let trace, debug;
|
||||
Utils.jsonSave("str",
|
||||
{_log: {trace: function(msg) { trace = msg; }}},
|
||||
"hi");
|
||||
do_check_true(!!trace);
|
||||
trace = undefined;
|
||||
Utils.jsonLoad("str",
|
||||
{_log: {trace: function(msg) { trace = msg; },
|
||||
debug: function(msg) { debug = msg; }}},
|
||||
function(val) { throw "exception"; });
|
||||
do_check_true(!!trace);
|
||||
do_check_true(!!debug);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
Cu.import("resource://services-sync/ext/StringBundle.js");
|
||||
|
||||
function run_test() {
|
||||
let fn = Utils.lazyStrings("sync");
|
||||
do_check_eq(typeof fn, "function");
|
||||
let bundle = fn();
|
||||
do_check_true(bundle instanceof StringBundle);
|
||||
let url = bundle.url;
|
||||
do_check_eq(url, "chrome://weave/locale/services/sync.properties");
|
||||
}
|
|
@ -1,7 +1,15 @@
|
|||
_("Make sure uri strings are converted to nsIURIs");
|
||||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
// both the makeURI and makeURL functions are tested
|
||||
// in this file
|
||||
|
||||
function run_test() {
|
||||
_test_makeURI();
|
||||
_test_makeURL();
|
||||
}
|
||||
|
||||
function _test_makeURI() {
|
||||
_("Check http uris");
|
||||
let uri1 = "http://mozillalabs.com/";
|
||||
do_check_eq(Utils.makeURI(uri1).spec, uri1);
|
||||
|
@ -57,3 +65,35 @@ function run_test() {
|
|||
do_check_eq(Utils.makeURI("chrome://badstuff"), undefined);
|
||||
do_check_eq(Utils.makeURI("this is a test"), undefined);
|
||||
}
|
||||
|
||||
function _test_makeURL() {
|
||||
_("Check http uri");
|
||||
let uri = "http://mozillalabs.com/";
|
||||
do_check_true(Utils.makeURL(uri) instanceof Ci.nsIURL);
|
||||
|
||||
_("Check https uri");
|
||||
let uris = "https://mozillalabs.com/";
|
||||
do_check_true(Utils.makeURL(uris) instanceof Ci.nsIURL);
|
||||
|
||||
let uric = "chrome://browser/content/browser.xul";
|
||||
do_check_true(Utils.makeURL(uric) instanceof Ci.nsIURL);
|
||||
|
||||
_("Check about uri");
|
||||
let uria = "about:weave";
|
||||
let except1;
|
||||
try {
|
||||
Utils.makeURL(uria);
|
||||
} catch(e) {
|
||||
except1 = e;
|
||||
}
|
||||
do_check_true(!!except1);
|
||||
|
||||
_("Check invalid uri");
|
||||
let except2;
|
||||
try {
|
||||
Utils.makeURL("mozillalabs.com");
|
||||
} catch(e) {
|
||||
except2 = e;
|
||||
}
|
||||
do_check_true(!!except2);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
_("Generated passphrase has length 20.");
|
||||
let pp = Utils.generatePassphrase();
|
||||
do_check_eq(pp.length, 20);
|
||||
|
||||
_("Passphrase only contains a-z.");
|
||||
let bytes = [chr.charCodeAt() for each (chr in pp)];
|
||||
do_check_true(Math.min.apply(null, bytes) >= 97);
|
||||
do_check_true(Math.max.apply(null, bytes) <= 122);
|
||||
|
||||
_("Hyphenated passphrase has 3 hyphens.");
|
||||
let hyphenated = Utils.hyphenatePassphrase(pp);
|
||||
do_check_eq(hyphenated.length, 23);
|
||||
do_check_eq(hyphenated[5], '-');
|
||||
do_check_eq(hyphenated[11], '-');
|
||||
do_check_eq(hyphenated[17], '-');
|
||||
do_check_eq(hyphenated.slice(0, 5) + hyphenated.slice(6, 11)
|
||||
+ hyphenated.slice(12, 17) + hyphenated.slice(18, 23), pp);
|
||||
|
||||
_("Normalize passphrase recognizes hyphens.");
|
||||
do_check_eq(Utils.normalizePassphrase(hyphenated), pp);
|
||||
do_check_eq(pp, pp);
|
||||
|
||||
_("Passphrase strength calculated according to the NIST algorithm.");
|
||||
do_check_eq(Utils.passphraseStrength(""), 0);
|
||||
do_check_eq(Utils.passphraseStrength("a"), 4);
|
||||
do_check_eq(Utils.passphraseStrength("ab"), 6);
|
||||
do_check_eq(Utils.passphraseStrength("abc"), 8);
|
||||
do_check_eq(Utils.passphraseStrength("abcdefgh"), 18);
|
||||
do_check_eq(Utils.passphraseStrength("abcdefghi"), 19.5);
|
||||
do_check_eq(Utils.passphraseStrength("abcdefghij"), 21);
|
||||
do_check_eq(Utils.passphraseStrength("abcdefghijklmnopqrst"), 36);
|
||||
do_check_eq(Utils.passphraseStrength("abcdefghijklmnopqrstu"), 37);
|
||||
do_check_eq(Utils.passphraseStrength("abcdefghijklmnopqrstuvwxyz"), 42);
|
||||
do_check_eq(Utils.passphraseStrength("abcdefghijklmnopqrstuvwxyz!"), 49);
|
||||
do_check_eq(Utils.passphraseStrength("1"), 10);
|
||||
do_check_eq(Utils.passphraseStrength("12"), 12);
|
||||
do_check_eq(Utils.passphraseStrength("a1"), 12);
|
||||
}
|
|
@ -63,6 +63,16 @@ function run_test() {
|
|||
let r10 = Utils.queryAsync(c("SELECT value, fieldname FROM moz_formhistory"), "fieldname");
|
||||
do_check_eq(r10.length, 3);
|
||||
|
||||
_("Generate an execution error");
|
||||
let r11, except, query = c("UPDATE moz_formhistory SET value = NULL WHERE fieldname = 'more'");
|
||||
try {
|
||||
r11 = Utils.queryAsync(query);
|
||||
} catch(e) {
|
||||
except = e;
|
||||
}
|
||||
do_check_true(!!except);
|
||||
do_check_eq(except.result, 19); // constraint violation error
|
||||
|
||||
_("Cleaning up");
|
||||
Utils.queryAsync(c("DELETE FROM moz_formhistory"));
|
||||
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
// both the checkStatus and ensureStatus functions are tested
|
||||
// here.
|
||||
|
||||
function run_test() {
|
||||
_test_checkStatus();
|
||||
_test_ensureStatus();
|
||||
}
|
||||
|
||||
function _test_checkStatus() {
|
||||
let msg = "msg";
|
||||
|
||||
_("test with default range");
|
||||
do_check_true(Utils.checkStatus(200, msg));
|
||||
do_check_true(Utils.checkStatus(299, msg));
|
||||
do_check_false(Utils.checkStatus(199, msg));
|
||||
do_check_false(Utils.checkStatus(300, msg));
|
||||
|
||||
_("test with a number");
|
||||
do_check_true(Utils.checkStatus(100, msg, [100]));
|
||||
do_check_false(Utils.checkStatus(200, msg, [100]));
|
||||
|
||||
_("test with two numbers");
|
||||
do_check_true(Utils.checkStatus(100, msg, [100, 200]));
|
||||
do_check_true(Utils.checkStatus(200, msg, [100, 200]));
|
||||
do_check_false(Utils.checkStatus(50, msg, [100, 200]));
|
||||
do_check_false(Utils.checkStatus(150, msg, [100, 200]));
|
||||
do_check_false(Utils.checkStatus(250, msg, [100, 200]));
|
||||
|
||||
_("test with a range and a number");
|
||||
do_check_true(Utils.checkStatus(50, msg, [[50, 100], 100]));
|
||||
do_check_true(Utils.checkStatus(75, msg, [[50, 100], 100]));
|
||||
do_check_true(Utils.checkStatus(100, msg, [[50, 100], 100]));
|
||||
do_check_false(Utils.checkStatus(200, msg, [[50, 100], 100]));
|
||||
|
||||
_("test with a number and a range");
|
||||
do_check_true(Utils.checkStatus(50, msg, [100, [50, 100]]));
|
||||
do_check_true(Utils.checkStatus(75, msg, [100, [50, 100]]));
|
||||
do_check_true(Utils.checkStatus(100, msg, [100, [50, 100]]));
|
||||
do_check_false(Utils.checkStatus(200, msg, [100, [50, 100]]));
|
||||
}
|
||||
|
||||
function _test_ensureStatus() {
|
||||
_("test that ensureStatus throws exception when it should");
|
||||
let except;
|
||||
try {
|
||||
Utils.ensureStatus(400, "msg", [200]);
|
||||
} catch(e) {
|
||||
except = e;
|
||||
}
|
||||
do_check_true(!!except);
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Cu.import("resource://services-sync/util.js");
|
||||
|
||||
function run_test() {
|
||||
let str = "Umlaute: \u00FC \u00E4\n"; // Umlaute: ü ä
|
||||
let encoded = Utils.encodeUTF8(str);
|
||||
let decoded = Utils.decodeUTF8(encoded);
|
||||
do_check_eq(decoded, str);
|
||||
}
|
Загрузка…
Ссылка в новой задаче