forked from mirrors/gecko-dev
This commit adds a new crate for bridging Rust Sync engines to Desktop, and a `mozIBridgedSyncEngine` for accessing the bridge via JS. Naturally, the bridge is called Golden Gate. 😊 For more information on how to use it, please see `golden_gate/src/lib.rs`. Other changes include: * Ensuring the test Sync server uses UTF-8 for requests and responses. * Renaming `mozISyncedBookmarksMirrorLogger` to `mozIServicesLogger`, and moving it into the shared Sync interfaces. The `BridgedEngine` trait lives in its own crate, called `golden_gate_traits`, to make it easier to eventually move into a-s. `Interruptee` and `Interrupted` already exist in a-s, and are duplicated in this crate for now. Differential Revision: https://phabricator.services.mozilla.com/D65268 --HG-- extra : moz-landing-system : lando
443 lines
14 KiB
JavaScript
443 lines
14 KiB
JavaScript
/* Any copyright is dedicated to the Public Domain.
|
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
|
|
const { Service } = ChromeUtils.import("resource://services-sync/service.js");
|
|
const { FileUtils } = ChromeUtils.import(
|
|
"resource://gre/modules/FileUtils.jsm"
|
|
);
|
|
|
|
const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
|
|
|
|
// Delay to wait before cleanup, to allow files to age.
|
|
// This is so large because the file timestamp granularity is per-second, and
|
|
// so otherwise we can end up with all of our files -- the ones we want to
|
|
// keep, and the ones we want to clean up -- having the same modified time.
|
|
const CLEANUP_DELAY = 2000;
|
|
const DELAY_BUFFER = 500; // Buffer for timers on different OS platforms.
|
|
|
|
var errorHandler = Service.errorHandler;
|
|
|
|
function run_test() {
|
|
validate_all_future_pings();
|
|
run_next_test();
|
|
}
|
|
|
|
add_test(function test_noOutput() {
|
|
// Ensure that the log appender won't print anything.
|
|
errorHandler._logManager._fileAppender.level = Log.Level.Fatal + 1;
|
|
|
|
// Clear log output from startup.
|
|
Svc.Prefs.set("log.appender.file.logOnSuccess", false);
|
|
Svc.Obs.notify("weave:service:sync:finish");
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLogOuter() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLogOuter);
|
|
// Clear again without having issued any output.
|
|
Svc.Prefs.set("log.appender.file.logOnSuccess", true);
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLogInner() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLogInner);
|
|
|
|
errorHandler._logManager._fileAppender.level = Log.Level.Trace;
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
|
|
// Fake a successful sync.
|
|
Svc.Obs.notify("weave:service:sync:finish");
|
|
});
|
|
});
|
|
|
|
add_test(function test_logOnSuccess_false() {
|
|
Svc.Prefs.set("log.appender.file.logOnSuccess", false);
|
|
|
|
let log = Log.repository.getLogger("Sync.Test.FileLog");
|
|
log.info("this won't show up");
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
|
// No log file was written.
|
|
Assert.ok(!logsdir.directoryEntries.hasMoreElements());
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
|
|
// Fake a successful sync.
|
|
Svc.Obs.notify("weave:service:sync:finish");
|
|
});
|
|
|
|
function readFile(file, callback) {
|
|
NetUtil.asyncFetch(
|
|
{
|
|
uri: NetUtil.newURI(file),
|
|
loadUsingSystemPrincipal: true,
|
|
},
|
|
function(inputStream, statusCode, request) {
|
|
let data = NetUtil.readInputStreamToString(
|
|
inputStream,
|
|
inputStream.available()
|
|
);
|
|
callback(statusCode, data);
|
|
}
|
|
);
|
|
}
|
|
|
|
add_test(function test_logOnSuccess_true() {
|
|
Svc.Prefs.set("log.appender.file.logOnSuccess", true);
|
|
|
|
let log = Log.repository.getLogger("Sync.Test.FileLog");
|
|
const MESSAGE = "this WILL show up";
|
|
log.info(MESSAGE);
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
|
|
|
// Exactly one log file was written.
|
|
let entries = logsdir.directoryEntries;
|
|
Assert.ok(entries.hasMoreElements());
|
|
let logfile = entries.getNext().QueryInterface(Ci.nsIFile);
|
|
Assert.equal(logfile.leafName.slice(-4), ".txt");
|
|
Assert.ok(logfile.leafName.startsWith("success-sync-"), logfile.leafName);
|
|
Assert.ok(!entries.hasMoreElements());
|
|
|
|
// Ensure the log message was actually written to file.
|
|
readFile(logfile, function(error, data) {
|
|
Assert.ok(Components.isSuccessCode(error));
|
|
Assert.notEqual(data.indexOf(MESSAGE), -1);
|
|
|
|
// Clean up.
|
|
try {
|
|
logfile.remove(false);
|
|
} catch (ex) {
|
|
dump("Couldn't delete file: " + ex.message + "\n");
|
|
// Stupid Windows box.
|
|
}
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Fake a successful sync.
|
|
Svc.Obs.notify("weave:service:sync:finish");
|
|
});
|
|
|
|
add_test(function test_sync_error_logOnError_false() {
|
|
Svc.Prefs.set("log.appender.file.logOnError", false);
|
|
|
|
let log = Log.repository.getLogger("Sync.Test.FileLog");
|
|
log.info("this won't show up");
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
|
// No log file was written.
|
|
Assert.ok(!logsdir.directoryEntries.hasMoreElements());
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
|
|
// Fake an unsuccessful sync.
|
|
Svc.Obs.notify("weave:service:sync:error");
|
|
});
|
|
|
|
add_test(function test_sync_error_logOnError_true() {
|
|
Svc.Prefs.set("log.appender.file.logOnError", true);
|
|
|
|
let log = Log.repository.getLogger("Sync.Test.FileLog");
|
|
const MESSAGE = "this WILL show up";
|
|
log.info(MESSAGE);
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
|
|
|
// Exactly one log file was written.
|
|
let entries = logsdir.directoryEntries;
|
|
Assert.ok(entries.hasMoreElements());
|
|
let logfile = entries.getNext().QueryInterface(Ci.nsIFile);
|
|
Assert.equal(logfile.leafName.slice(-4), ".txt");
|
|
Assert.ok(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
|
Assert.ok(!entries.hasMoreElements());
|
|
|
|
// Ensure the log message was actually written to file.
|
|
readFile(logfile, function(error, data) {
|
|
Assert.ok(Components.isSuccessCode(error));
|
|
Assert.notEqual(data.indexOf(MESSAGE), -1);
|
|
|
|
// Clean up.
|
|
try {
|
|
logfile.remove(false);
|
|
} catch (ex) {
|
|
dump("Couldn't delete file: " + ex.message + "\n");
|
|
// Stupid Windows box.
|
|
}
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Fake an unsuccessful sync.
|
|
Svc.Obs.notify("weave:service:sync:error");
|
|
});
|
|
|
|
add_test(function test_login_error_logOnError_false() {
|
|
Svc.Prefs.set("log.appender.file.logOnError", false);
|
|
|
|
let log = Log.repository.getLogger("Sync.Test.FileLog");
|
|
log.info("this won't show up");
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
|
// No log file was written.
|
|
Assert.ok(!logsdir.directoryEntries.hasMoreElements());
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
|
|
// Fake an unsuccessful login.
|
|
Svc.Obs.notify("weave:service:login:error");
|
|
});
|
|
|
|
add_test(function test_login_error_logOnError_true() {
|
|
Svc.Prefs.set("log.appender.file.logOnError", true);
|
|
|
|
let log = Log.repository.getLogger("Sync.Test.FileLog");
|
|
const MESSAGE = "this WILL show up";
|
|
log.info(MESSAGE);
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
|
|
|
// Exactly one log file was written.
|
|
let entries = logsdir.directoryEntries;
|
|
Assert.ok(entries.hasMoreElements());
|
|
let logfile = entries.getNext().QueryInterface(Ci.nsIFile);
|
|
Assert.equal(logfile.leafName.slice(-4), ".txt");
|
|
Assert.ok(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
|
Assert.ok(!entries.hasMoreElements());
|
|
|
|
// Ensure the log message was actually written to file.
|
|
readFile(logfile, function(error, data) {
|
|
Assert.ok(Components.isSuccessCode(error));
|
|
Assert.notEqual(data.indexOf(MESSAGE), -1);
|
|
|
|
// Clean up.
|
|
try {
|
|
logfile.remove(false);
|
|
} catch (ex) {
|
|
dump("Couldn't delete file: " + ex.message + "\n");
|
|
// Stupid Windows box.
|
|
}
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Fake an unsuccessful login.
|
|
Svc.Obs.notify("weave:service:login:error");
|
|
});
|
|
|
|
add_test(function test_noNewFailed_noErrorLog() {
|
|
Svc.Prefs.set("log.appender.file.logOnError", true);
|
|
Svc.Prefs.set("log.appender.file.logOnSuccess", false);
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
|
// No log file was written.
|
|
Assert.ok(!logsdir.directoryEntries.hasMoreElements());
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
// failed is nonzero and newFailed is zero -- shouldn't write a log.
|
|
let count = {
|
|
applied: 8,
|
|
succeeded: 4,
|
|
failed: 5,
|
|
newFailed: 0,
|
|
reconciled: 4,
|
|
};
|
|
Svc.Obs.notify("weave:engine:sync:applied", count, "foobar-engine");
|
|
Svc.Obs.notify("weave:service:sync:finish");
|
|
});
|
|
|
|
add_test(function test_newFailed_errorLog() {
|
|
Svc.Prefs.set("log.appender.file.logOnError", true);
|
|
Svc.Prefs.set("log.appender.file.logOnSuccess", false);
|
|
|
|
let log = Log.repository.getLogger("Sync.Test.FileLog");
|
|
const MESSAGE = "this WILL show up 2";
|
|
log.info(MESSAGE);
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
|
|
|
// Exactly one log file was written.
|
|
let entries = logsdir.directoryEntries;
|
|
Assert.ok(entries.hasMoreElements());
|
|
let logfile = entries.getNext().QueryInterface(Ci.nsIFile);
|
|
Assert.equal(logfile.leafName.slice(-4), ".txt");
|
|
Assert.ok(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
|
Assert.ok(!entries.hasMoreElements());
|
|
|
|
// Ensure the log message was actually written to file.
|
|
readFile(logfile, function(error, data) {
|
|
Assert.ok(Components.isSuccessCode(error));
|
|
Assert.notEqual(data.indexOf(MESSAGE), -1);
|
|
|
|
// Clean up.
|
|
try {
|
|
logfile.remove(false);
|
|
} catch (ex) {
|
|
dump("Couldn't delete file: " + ex.message + "\n");
|
|
// Stupid Windows box.
|
|
}
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
});
|
|
// newFailed is nonzero -- should write a log.
|
|
let count = {
|
|
applied: 8,
|
|
succeeded: 4,
|
|
failed: 5,
|
|
newFailed: 4,
|
|
reconciled: 4,
|
|
};
|
|
|
|
Svc.Obs.notify("weave:engine:sync:applied", count, "foobar-engine");
|
|
Svc.Obs.notify("weave:service:sync:finish");
|
|
});
|
|
|
|
add_test(function test_errorLog_dumpAddons() {
|
|
Svc.Prefs.set("log.logger", "Trace");
|
|
Svc.Prefs.set("log.appender.file.logOnError", true);
|
|
|
|
Svc.Obs.add("weave:service:reset-file-log", function onResetFileLog() {
|
|
Svc.Obs.remove("weave:service:reset-file-log", onResetFileLog);
|
|
|
|
let entries = logsdir.directoryEntries;
|
|
Assert.ok(entries.hasMoreElements());
|
|
let logfile = entries.getNext().QueryInterface(Ci.nsIFile);
|
|
Assert.equal(logfile.leafName.slice(-4), ".txt");
|
|
Assert.ok(logfile.leafName.startsWith("error-sync-"), logfile.leafName);
|
|
Assert.ok(!entries.hasMoreElements());
|
|
|
|
// Ensure we logged some addon list (which is probably empty)
|
|
readFile(logfile, function(error, data) {
|
|
Assert.ok(Components.isSuccessCode(error));
|
|
Assert.notEqual(data.indexOf("Addons installed"), -1);
|
|
|
|
// Clean up.
|
|
try {
|
|
logfile.remove(false);
|
|
} catch (ex) {
|
|
dump("Couldn't delete file: " + ex.message + "\n");
|
|
// Stupid Windows box.
|
|
}
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
});
|
|
});
|
|
|
|
// Fake an unsuccessful sync.
|
|
Svc.Obs.notify("weave:service:sync:error");
|
|
});
|
|
|
|
// Check that error log files are deleted above an age threshold.
|
|
add_test(function test_logErrorCleanup_age() {
|
|
_("Beginning test_logErrorCleanup_age.");
|
|
let maxAge = CLEANUP_DELAY / 1000;
|
|
let oldLogs = [];
|
|
let numLogs = 10;
|
|
let errString = "some error log\n";
|
|
|
|
Svc.Prefs.set("log.appender.file.logOnError", true);
|
|
Svc.Prefs.set("log.appender.file.maxErrorAge", maxAge);
|
|
|
|
_("Making some files.");
|
|
for (let i = 0; i < numLogs; i++) {
|
|
let now = Date.now();
|
|
let filename = "error-sync-" + now + "" + i + ".txt";
|
|
let newLog = FileUtils.getFile("ProfD", ["weave", "logs", filename]);
|
|
let foStream = FileUtils.openFileOutputStream(newLog);
|
|
foStream.write(errString, errString.length);
|
|
foStream.close();
|
|
_(" > Created " + filename);
|
|
oldLogs.push(newLog.leafName);
|
|
}
|
|
|
|
Svc.Obs.add(
|
|
"services-tests:common:log-manager:cleanup-logs",
|
|
function onCleanupLogs() {
|
|
Svc.Obs.remove(
|
|
"services-tests:common:log-manager:cleanup-logs",
|
|
onCleanupLogs
|
|
);
|
|
|
|
// Only the newest created log file remains.
|
|
let entries = logsdir.directoryEntries;
|
|
Assert.ok(entries.hasMoreElements());
|
|
let logfile = entries.getNext().QueryInterface(Ci.nsIFile);
|
|
Assert.ok(
|
|
oldLogs.every(function(e) {
|
|
return e != logfile.leafName;
|
|
})
|
|
);
|
|
Assert.ok(!entries.hasMoreElements());
|
|
|
|
// Clean up.
|
|
try {
|
|
logfile.remove(false);
|
|
} catch (ex) {
|
|
dump("Couldn't delete file: " + ex.message + "\n");
|
|
// Stupid Windows box.
|
|
}
|
|
|
|
Svc.Prefs.resetBranch("");
|
|
run_next_test();
|
|
}
|
|
);
|
|
|
|
let delay = CLEANUP_DELAY + DELAY_BUFFER;
|
|
|
|
_("Cleaning up logs after " + delay + "msec.");
|
|
CommonUtils.namedTimer(
|
|
function onTimer() {
|
|
Svc.Obs.notify("weave:service:sync:error");
|
|
},
|
|
delay,
|
|
this,
|
|
"cleanup-timer"
|
|
);
|
|
});
|
|
|
|
add_task(async function test_remove_log_on_startOver() {
|
|
Svc.Prefs.set("log.appender.file.logOnError", true);
|
|
|
|
let log = Log.repository.getLogger("Sync.Test.FileLog");
|
|
const MESSAGE = "this WILL show up";
|
|
log.info(MESSAGE);
|
|
|
|
let promiseLogWritten = promiseOneObserver("weave:service:reset-file-log");
|
|
// Fake an unsuccessful sync.
|
|
Svc.Obs.notify("weave:service:sync:error");
|
|
|
|
await promiseLogWritten;
|
|
// Should have at least 1 log file.
|
|
let entries = logsdir.directoryEntries;
|
|
Assert.ok(entries.hasMoreElements());
|
|
|
|
// Fake a reset.
|
|
let promiseRemoved = promiseOneObserver("weave:service:remove-file-log");
|
|
Svc.Obs.notify("weave:service:start-over:finish");
|
|
await promiseRemoved;
|
|
|
|
// should be no files left.
|
|
Assert.ok(!logsdir.directoryEntries.hasMoreElements());
|
|
});
|