Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Bug 753515 - Move json{Load,Save} from services-sync into services-co…
…mmon; r=mconnor

--HG--
rename : services/sync/tests/unit/test_utils_json.js => services/common/tests/unit/test_utils_json.js
  • Loading branch information
indygreg committed May 10, 2012
1 parent e23436c commit cc98aa7
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 102 deletions.
13 changes: 13 additions & 0 deletions services/common/tests/unit/head_helpers.js
Expand Up @@ -127,6 +127,19 @@ function readBytesFromInputStream(inputStream, count) {
return new BinaryInputStream(inputStream).readBytes(count);
}

/*
* Ensure exceptions from inside callbacks leads to test failures.
*/
function ensureThrows(func) {
return function() {
try {
func.apply(this, arguments);
} catch (ex) {
do_throw(ex);
}
};
}

/**
* Proxy auth helpers.
*/
Expand Down
@@ -1,16 +1,18 @@
_("Make sure json saves and loads from disk");
Cu.import("resource://services-sync/util.js");
Cu.import("resource://services-sync/constants.js");
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */

Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://services-common/utils.js");

function run_test() {
initTestLogging();
run_next_test();
}

add_test(function test_roundtrip() {
_("Do a simple write of an array to json and read");
Utils.jsonSave("foo", {}, ["v1", "v2"], ensureThrows(function() {
Utils.jsonLoad("foo", {}, ensureThrows(function(val) {
CommonUtils.jsonSave("foo", {}, ["v1", "v2"], ensureThrows(function() {
CommonUtils.jsonLoad("foo", {}, ensureThrows(function(val) {
let foo = val;
do_check_eq(typeof foo, "object");
do_check_eq(foo.length, 2);
Expand All @@ -23,8 +25,8 @@ add_test(function test_roundtrip() {

add_test(function test_string() {
_("Try saving simple strings");
Utils.jsonSave("str", {}, "hi", ensureThrows(function() {
Utils.jsonLoad("str", {}, ensureThrows(function(val) {
CommonUtils.jsonSave("str", {}, "hi", ensureThrows(function() {
CommonUtils.jsonLoad("str", {}, ensureThrows(function(val) {
let str = val;
do_check_eq(typeof str, "string");
do_check_eq(str.length, 2);
Expand All @@ -37,8 +39,8 @@ add_test(function test_string() {

add_test(function test_number() {
_("Try saving a number");
Utils.jsonSave("num", {}, 42, ensureThrows(function() {
Utils.jsonLoad("num", {}, ensureThrows(function(val) {
CommonUtils.jsonSave("num", {}, 42, ensureThrows(function() {
CommonUtils.jsonLoad("num", {}, ensureThrows(function(val) {
let num = val;
do_check_eq(typeof num, "number");
do_check_eq(num, 42);
Expand All @@ -49,17 +51,17 @@ add_test(function test_number() {

add_test(function test_nonexistent_file() {
_("Try loading a non-existent file.");
Utils.jsonLoad("non-existent", {}, ensureThrows(function(val) {
CommonUtils.jsonLoad("non-existent", {}, ensureThrows(function(val) {
do_check_eq(val, undefined);
run_next_test();
}));
}));
});

add_test(function test_save_logging() {
_("Verify that writes are logged.");
let trace;
Utils.jsonSave("log", {_log: {trace: function(msg) { trace = msg; }}},
"hi", ensureThrows(function () {
CommonUtils.jsonSave("log", {_log: {trace: function(msg) { trace = msg; }}},
"hi", ensureThrows(function () {
do_check_true(!!trace);
run_next_test();
}));
Expand All @@ -69,7 +71,7 @@ add_test(function test_load_logging() {
_("Verify that reads and read errors are logged.");

// Write a file with some invalid JSON
let filePath = "weave/log.json";
let filePath = "log.json";
let file = FileUtils.getFile("ProfD", filePath.split("/"), true);
let fos = Cc["@mozilla.org/network/file-output-stream;1"]
.createInstance(Ci.nsIFileOutputStream);
Expand All @@ -83,10 +85,18 @@ add_test(function test_load_logging() {
stream.close();

let trace, debug;
Utils.jsonLoad("log",
{_log: {trace: function(msg) { trace = msg; },
debug: function(msg) { debug = msg; }}},
ensureThrows(function(val) {
let obj = {
_log: {
trace: function(msg) {
trace = msg;
},
debug: function(msg) {
debug = msg;
}
}
};
CommonUtils.jsonLoad("log", obj, ensureThrows(function(val) {
do_check_true(!val);
do_check_true(!!trace);
do_check_true(!!debug);
run_next_test();
Expand Down
1 change: 1 addition & 0 deletions services/common/tests/unit/xpcshell.ini
Expand Up @@ -7,6 +7,7 @@ tail =

[test_utils_atob.js]
[test_utils_encodeBase32.js]
[test_utils_json.js]
[test_utils_makeURI.js]
[test_utils_namedTimer.js]
[test_utils_stackTrace.js]
Expand Down
83 changes: 83 additions & 0 deletions services/common/utils.js
Expand Up @@ -6,6 +6,8 @@ const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;

const EXPORTED_SYMBOLS = ["CommonUtils"];

Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://services-common/log4moz.js");
Expand Down Expand Up @@ -300,6 +302,87 @@ let CommonUtils = {
let over = len % 4;
return over ? atob(b64.substr(0, len - over)) : atob(b64);
},

/**
* Load a JSON file from disk in the profile directory.
*
* @param filePath
* JSON file path load from profile. Loaded file will be
* <profile>/<filePath>.json. i.e. Do not specify the ".json"
* extension.
* @param that
* Object to use for logging and "this" for callback.
* @param callback
* Function to process json object as its first argument. If the file
* could not be loaded, the first argument will be undefined.
*/
jsonLoad: function jsonLoad(filePath, that, callback) {
let path = filePath + ".json";

if (that._log) {
that._log.trace("Loading json from disk: " + filePath);
}

let file = FileUtils.getFile("ProfD", path.split("/"), true);
if (!file.exists()) {
callback.call(that);
return;
}

let channel = NetUtil.newChannel(file);
channel.contentType = "application/json";

NetUtil.asyncFetch(channel, function (is, result) {
if (!Components.isSuccessCode(result)) {
callback.call(that);
return;
}
let string = NetUtil.readInputStreamToString(is, is.available());
is.close();
let json;
try {
json = JSON.parse(string);
} catch (ex) {
if (that._log) {
that._log.debug("Failed to load json: " +
CommonUtils.exceptionStr(ex));
}
}
callback.call(that, json);
});
},

/**
* Save a json-able object to disk in the profile directory.
*
* @param filePath
* JSON file path save to <filePath>.json
* @param that
* Object to use for logging and "this" for callback
* @param obj
* Function to provide json-able object to save. If this isn't a
* function, it'll be used as the object to make a json string.
* @param callback
* Function called when the write has been performed. Optional.
*/
jsonSave: function jsonSave(filePath, that, obj, callback) {
let path = filePath + ".json";
if (that._log) {
that._log.trace("Saving json to disk: " + path);
}

let file = FileUtils.getFile("ProfD", path.split("/"), true);
let json = typeof obj == "function" ? obj.call(that) : obj;
let out = JSON.stringify(json);

let fos = FileUtils.openSafeFileOutputStream(file);
let is = this._utf8Converter.convertToInputStream(out);
NetUtil.asyncCopy(is, fos, function (result) {
if (typeof callback == "function") {
callback.call(that);
}
});
},
};

XPCOMUtils.defineLazyGetter(CommonUtils, "_utf8Converter", function() {
Expand Down
73 changes: 4 additions & 69 deletions services/sync/modules/util.js
Expand Up @@ -357,77 +357,12 @@ let Utils = {
return Utils.encodeKeyBase32(atob(encodedKey));
},

/**
* Load a json object from disk
*
* @param filePath
* Json file path load from weave/[filePath].json
* @param that
* Object to use for logging and "this" for callback
* @param callback
* Function to process json object as its first parameter
*/
jsonLoad: function Utils_jsonLoad(filePath, that, callback) {
filePath = "weave/" + filePath + ".json";
if (that._log)
that._log.trace("Loading json from disk: " + filePath);

let file = FileUtils.getFile("ProfD", filePath.split("/"), true);
if (!file.exists()) {
callback.call(that);
return;
}

let channel = NetUtil.newChannel(file);
channel.contentType = "application/json";

NetUtil.asyncFetch(channel, function (is, result) {
if (!Components.isSuccessCode(result)) {
callback.call(that);
return;
}
let string = NetUtil.readInputStreamToString(is, is.available());
is.close();
let json;
try {
json = JSON.parse(string);
} catch (ex) {
if (that._log)
that._log.debug("Failed to load json: " + Utils.exceptionStr(ex));
}
callback.call(that, json);
});
jsonLoad: function jsonLoad(path, that, callback) {
CommonUtils.jsonLoad("weave/" + path, that, callback);
},

/**
* Save a json-able object to disk
*
* @param filePath
* Json file path save to weave/[filePath].json
* @param that
* Object to use for logging and "this" for callback
* @param obj
* Function to provide json-able object to save. If this isn't a
* function, it'll be used as the object to make a json string.
* @param callback
* Function called when the write has been performed. Optional.
*/
jsonSave: function Utils_jsonSave(filePath, that, obj, callback) {
filePath = "weave/" + filePath + ".json";
if (that._log)
that._log.trace("Saving json to disk: " + filePath);

let file = FileUtils.getFile("ProfD", filePath.split("/"), true);
let json = typeof obj == "function" ? obj.call(that) : obj;
let out = JSON.stringify(json);

let fos = FileUtils.openSafeFileOutputStream(file);
let is = this._utf8Converter.convertToInputStream(out);
NetUtil.asyncCopy(is, fos, function (result) {
if (typeof callback == "function") {
callback.call(that);
}
});
jsonSave: function jsonSave(path, that, obj, callback) {
CommonUtils.jsonSave("weave/" + path, that, obj, callback);
},

getIcon: function(iconUri, defaultIcon) {
Expand Down
14 changes: 0 additions & 14 deletions services/sync/tests/unit/head_helpers.js
Expand Up @@ -251,20 +251,6 @@ function SyncTestingInfrastructure(username, password, syncKey) {
this.fakeCryptoService = new FakeCryptoService();
}

/*
* Ensure exceptions from inside callbacks leads to test failures.
*/
function ensureThrows(func) {
return function() {
try {
func.apply(this, arguments);
} catch (ex) {
do_throw(ex);
}
};
}


_("Setting the identity for passphrase");
Cu.import("resource://services-sync/identity.js");

Expand Down
1 change: 0 additions & 1 deletion services/sync/tests/unit/xpcshell.ini
Expand Up @@ -18,7 +18,6 @@ tail =
[test_utils_keyEncoding.js]
[test_utils_getErrorString.js]
[test_utils_getIcon.js]
[test_utils_json.js]
[test_utils_lazyStrings.js]
[test_utils_lock.js]
[test_utils_makeGUID.js]
Expand Down

0 comments on commit cc98aa7

Please sign in to comment.