From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../sync/tests/unit/test_errorhandler_filelog.js | 450 +++++++++++++++++++++ 1 file changed, 450 insertions(+) create mode 100644 services/sync/tests/unit/test_errorhandler_filelog.js (limited to 'services/sync/tests/unit/test_errorhandler_filelog.js') diff --git a/services/sync/tests/unit/test_errorhandler_filelog.js b/services/sync/tests/unit/test_errorhandler_filelog.js new file mode 100644 index 0000000000..5e1e36061f --- /dev/null +++ b/services/sync/tests/unit/test_errorhandler_filelog.js @@ -0,0 +1,450 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +// `Service` is used as a global in head_helpers.js. +// eslint-disable-next-line no-unused-vars +const { Service } = ChromeUtils.importESModule( + "resource://services-sync/service.sys.mjs" +); +const { logManager } = ChromeUtils.import( + "resource://gre/modules/FxAccountsCommon.js" +); +const { FileUtils } = ChromeUtils.importESModule( + "resource://gre/modules/FileUtils.sys.mjs" +); + +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. + +function run_test() { + validate_all_future_pings(); + run_next_test(); +} + +add_test(function test_noOutput() { + // Ensure that the log appender won't print anything. + 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); + + 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(async 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."); + const logsDir = PathUtils.join(PathUtils.profileDir, "weave", "logs"); + await IOUtils.makeDirectory(logsDir); + for (let i = 0; i < numLogs; i++) { + let now = Date.now(); + let filename = "error-sync-" + now + "" + i + ".txt"; + let newLog = new FileUtils.File(PathUtils.join(logsDir, 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()); +}); -- cgit v1.2.3