Bug 828204 - Make if DEBUG statements internal to LOG in osfile. Add new TEST flag for logging into Console.services. r=yoric

This commit is contained in:
Yura Zenevich 2013-02-16 10:40:15 -05:00
parent 36c39ecc98
commit c80968a8c2
6 changed files with 115 additions and 79 deletions

View File

@ -39,7 +39,7 @@ Queue.prototype = {
*
* @param {string} url The url containing the source code for this worker,
* as in constructor ChromeWorker.
* @param {Function=} log Optionally, a logging function.
* @param {Function} log A logging function.
*
* @constructor
*/
@ -47,8 +47,8 @@ function PromiseWorker(url, log) {
if (typeof url != "string") {
throw new TypeError("Expecting a string");
}
if (log != null && typeof log != "function") {
throw new TypeError("Expecting either null or a function");
if (typeof log !== "function") {
throw new TypeError("log is expected to be a function");
}
this._log = log;
this._url = url;
@ -98,9 +98,7 @@ PromiseWorker.prototype = {
* @param {Error} error Some JS error.
*/
worker.onerror = function onerror(error) {
if (self._log) {
self._log("Received uncaught error from worker", JSON.stringify(error.message), error.message);
}
self._log("Received uncaught error from worker", error.message);
error.preventDefault();
let {deferred} = self._queue.pop();
deferred.reject(error);
@ -120,9 +118,7 @@ PromiseWorker.prototype = {
* @param {*} msg The message received from the worker.
*/
worker.onmessage = function onmessage(msg) {
if (self._log) {
self._log("Received message from worker", JSON.stringify(msg.data));
}
self._log("Received message from worker", msg.data);
let handler = self._queue.pop();
let deferred = handler.deferred;
let data = msg.data;
@ -158,14 +154,10 @@ PromiseWorker.prototype = {
let deferred = Promise.defer();
let id = ++this._id;
let message = {fun: fun, args: array, id: id};
if (this._log) {
this._log("Posting message", JSON.stringify(message));
}
this._log("Posting message", message);
this._queue.push({deferred:deferred, closure: closure, id: id});
this._worker.postMessage(message);
if (this._log) {
this._log("Message posted");
}
this._log("Message posted");
return deferred.promise;
}
};

View File

@ -89,8 +89,7 @@ const noOptions = {};
let worker = new PromiseWorker(
"resource://gre/modules/osfile/osfile_async_worker.js",
DEBUG?LOG:null);
"resource://gre/modules/osfile/osfile_async_worker.js", LOG);
let Scheduler = {
post: function post(...args) {
let promise = worker.post.apply(worker, args);

View File

@ -16,8 +16,6 @@ if (this.Components) {
importScripts("resource://gre/modules/osfile.jsm");
let LOG = exports.OS.Shared.LOG.bind(exports.OS.Shared.LOG, "Agent");
// A simple flag used to control debugging messages.
let DEBUG = exports.OS.Shared.DEBUG;
/**
* Communications with the controller.
@ -30,35 +28,25 @@ if (this.Components) {
*/
self.onmessage = function onmessage(msg) {
let data = msg.data;
if (DEBUG) {
LOG("Received message", JSON.stringify(data));
}
LOG("Received message", data);
let id = data.id;
let result;
let exn;
try {
let method = data.fun;
if (DEBUG) {
LOG("Calling method", method);
}
LOG("Calling method", method);
result = Agent[method].apply(Agent, data.args);
if (DEBUG) {
LOG("Method", method, "succeeded");
}
LOG("Method", method, "succeeded");
} catch (ex) {
exn = ex;
if (DEBUG) {
LOG("Error while calling agent method", exn, exn.stack);
}
LOG("Error while calling agent method", exn, exn.stack);
}
// Now, post a reply, possibly as an uncaught error.
// We post this message from outside the |try ... catch| block
// to avoid capturing errors that take place during |postMessage| and
// built-in serialization.
if (!exn) {
if (DEBUG) {
LOG("Sending positive reply", JSON.stringify(result), "id is", id);
}
LOG("Sending positive reply", result, "id is", id);
if (result instanceof Transfer) {
// Take advantage of zero-copy transfers
self.postMessage({ok: result.data, id: id}, result.transfers);
@ -67,22 +55,16 @@ if (this.Components) {
}
} else if (exn == StopIteration) {
// StopIteration cannot be serialized automatically
if (DEBUG) {
LOG("Sending back StopIteration");
}
LOG("Sending back StopIteration");
self.postMessage({StopIteration: true, id: id});
} else if (exn instanceof exports.OS.File.Error) {
if (DEBUG) {
LOG("Sending back OS.File error", exn, "id is", id);
}
LOG("Sending back OS.File error", exn, "id is", id);
// Instances of OS.File.Error know how to serialize themselves
// (deserialization ensures that we end up with OS-specific
// instances of |OS.File.Error|)
self.postMessage({fail: exports.OS.File.Error.toMsg(exn), id:id});
} else {
if (DEBUG) {
LOG("Sending back regular error", exn, exn.stack, "id is", id);
}
LOG("Sending back regular error", exn, exn.stack, "id is", id);
// Other exceptions do not, and should be propagated through DOM's
// built-in mechanism for uncaught errors, although this mechanism
// may lose interesting information.
@ -202,14 +184,14 @@ if (this.Components) {
* back the results.
*/
let Agent = {
// Update DEBUG flag message from controller.
// Update worker's OS.Shared.DEBUG flag message from controller.
SET_DEBUG: function SET_DEBUG (aDEBUG) {
DEBUG = aDEBUG;
exports.OS.Shared.DEBUG = aDEBUG;
},
// Return current DEBUG value to controller.
// Return worker's current OS.Shared.DEBUG value to controller.
// Note: This is used for testing purposes.
GET_DEBUG: function GET_DEBUG () {
return DEBUG;
return exports.OS.Shared.DEBUG;
},
// Functions of OS.File
stat: function stat(path) {

View File

@ -101,7 +101,48 @@
dump(text + "\n");
};
}
exports.OS.Shared.LOG = LOG;
/**
* Apply JSON.stringify to an argument of type object.
* Return itself otherwise.
*
* @param arg An argument to be stringified if possible.
*/
let stringifyArg = function stringifyArg(arg) {
if (typeof arg === "string") {
return arg;
}
if (arg && typeof arg === "object") {
return JSON.stringify(arg);
}
return arg;
};
/**
* A Shared LOG utility function that only logs when DEBUG is set.
*
* @params {string|object}
* An arbitrary number of arguments to be logged.
*/
exports.OS.Shared.LOG = function (...args) {
// If DEBUG is falsy, do nothing.
if (!exports.OS.Shared.DEBUG) {
return;
}
let logFunc = LOG;
if (exports.OS.Shared.TEST && Services) {
// If TEST is true and the file is loaded in the main thread,
// use Services.console for logging and listening to.
logFunc = function logFunc(...args) {
let message = ["TEST", "OS"].concat(args).join(" ");
Services.console.logStringMessage(message + "\n");
};
}
logFunc.apply(null, [stringifyArg(arg) for (arg of args)]);
};
/**
* An OS error.
@ -383,10 +424,8 @@
};
function projector(type, signed) {
if (exports.OS.Shared.DEBUG) {
LOG("Determining best projection for", type,
"(size: ", type.size, ")", signed?"signed":"unsigned");
}
exports.OS.Shared.LOG("Determining best projection for", type,
"(size: ", type.size, ")", signed?"signed":"unsigned");
if (type instanceof Type) {
type = type.implementation;
}
@ -402,22 +441,16 @@
|| type == ctypes.ssize_t
|| type == ctypes.intptr_t
|| type == ctypes.uintptr_t
|| type == ctypes.off_t){
if (signed) {
if (exports.OS.Shared.DEBUG) {
LOG("Projected as a large signed integer");
}
return projectLargeInt;
} else {
if (exports.OS.Shared.DEBUG) {
LOG("Projected as a large unsigned integer");
}
return projectLargeUInt;
}
}
if (exports.OS.Shared.DEBUG) {
LOG("Projected as a regular number");
|| type == ctypes.off_t) {
if (signed) {
exports.OS.Shared.LOG("Projected as a large signed integer");
return projectLargeInt;
} else {
exports.OS.Shared.LOG("Projected as a large unsigned integer");
return projectLargeUInt;
}
}
exports.OS.Shared.LOG("Projected as a regular number");
return projectValue;
};
exports.OS.Shared.projectValue = projectValue;
@ -820,9 +853,7 @@
// thread
let declareFFI = function declareFFI(lib, symbol, abi,
returnType /*, argTypes ...*/) {
if (exports.OS.Shared.DEBUG) {
LOG("Attempting to declare FFI ", symbol);
}
exports.OS.Shared.LOG("Attempting to declare FFI ", symbol);
// We guard agressively, to avoid any late surprise
if (typeof symbol != "string") {
throw new TypeError("declareFFI expects as first argument a string");
@ -860,16 +891,12 @@
if (exports.OS.Shared.DEBUG) {
result.fun = fun; // Also return the raw FFI function.
}
if (exports.OS.Shared.DEBUG) {
LOG("Function", symbol, "declared");
}
exports.OS.Shared.LOG("Function", symbol, "declared");
return result;
} catch (x) {
// Note: Not being able to declare a function is normal.
// Some functions are OS (or OS version)-specific.
if (exports.OS.Shared.DEBUG) {
LOG("Could not declare function " + symbol, x);
}
exports.OS.Shared.LOG("Could not declare function ", symbol, x);
return null;
}
};

View File

@ -47,9 +47,7 @@ if (typeof Components != "undefined") {
libc = ctypes.open(libc_candidates[i]);
break;
} catch (x) {
if (exports.OS.Shared.DEBUG) {
LOG("Could not open libc "+libc_candidates[i]);
}
LOG("Could not open libc ", libc_candidates[i]);
}
}
if (!libc) {

View File

@ -140,6 +140,7 @@ let test = maketest("Main", function main(test) {
yield test_mkdir();
yield test_iter();
yield test_exists();
yield test_debug_test();
info("Test is over");
SimpleTest.finish();
});
@ -654,3 +655,40 @@ let test_debug = maketest("debug", function debug(test) {
test.is(workerDEBUG, false, "Worker's DEBUG is unset.");
});
});
/**
* Test logging in the main thread with set OS.Shared.DEBUG and
* OS.Shared.TEST flags.
*/
let test_debug_test = maketest("debug_test", function debug_test(test) {
return Task.spawn(function () {
// Create a console listener.
let consoleListener = {
observe: function (aMessage) {
// Ignore unexpected messages.
if (!(aMessage instanceof Components.interfaces.nsIConsoleMessage)) {
return;
}
if (aMessage.message.indexOf("TEST OS") < 0) {
return;
}
test.ok(true, "DEBUG TEST messages are logged correctly.")
}
};
// Set/Unset OS.Shared.DEBUG, OS.Shared.TEST and the console listener.
function toggleDebugTest (pref) {
OS.Shared.DEBUG = pref;
OS.Shared.TEST = pref;
Services.console[pref ? "registerListener" : "unregisterListener"](
consoleListener);
}
// Save original DEBUG value.
let originalPref = OS.Shared.DEBUG;
toggleDebugTest(true);
// Execution of OS.File.exist method will trigger OS.File.LOG several times.
let fileExists = yield OS.File.exists(EXISTING_FILE);
toggleDebugTest(false);
// Restore DEBUG to its original.
OS.Shared.DEBUG = originalPref;
});
});