michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: michael@0: Components.utils.import("resource://gre/modules/Services.jsm"); michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: michael@0: createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "10.0"); michael@0: michael@0: let prefService = Services.prefs; michael@0: let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]. michael@0: getService(Ci.nsIAppStartup); michael@0: michael@0: const pref_last_success = "toolkit.startup.last_success"; michael@0: const pref_recent_crashes = "toolkit.startup.recent_crashes"; michael@0: const pref_max_resumed_crashes = "toolkit.startup.max_resumed_crashes"; michael@0: const pref_always_use_safe_mode = "toolkit.startup.always_use_safe_mode"; michael@0: michael@0: function run_test() { michael@0: prefService.setBoolPref(pref_always_use_safe_mode, true); michael@0: michael@0: resetTestEnv(0); michael@0: michael@0: test_trackStartupCrashBegin(); michael@0: test_trackStartupCrashEnd(); michael@0: test_trackStartupCrashBegin_safeMode(); michael@0: test_trackStartupCrashEnd_safeMode(); michael@0: test_maxResumed(); michael@0: resetTestEnv(0); michael@0: michael@0: prefService.clearUserPref(pref_always_use_safe_mode); michael@0: } michael@0: michael@0: // reset prefs to default michael@0: function resetTestEnv(replacedLockTime) { michael@0: try { michael@0: // call begin to reset mStartupCrashTrackingEnded michael@0: appStartup.trackStartupCrashBegin(); michael@0: } catch (x) { } michael@0: prefService.setIntPref(pref_max_resumed_crashes, 2); michael@0: prefService.clearUserPref(pref_recent_crashes); michael@0: gAppInfo.replacedLockTime = replacedLockTime; michael@0: prefService.clearUserPref(pref_last_success); michael@0: } michael@0: michael@0: function now_seconds() { michael@0: return ms_to_s(Date.now()); michael@0: } michael@0: michael@0: function ms_to_s(ms) { michael@0: return Math.floor(ms / 1000); michael@0: } michael@0: michael@0: function test_trackStartupCrashBegin() { michael@0: let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); michael@0: do_check_false(gAppInfo.inSafeMode); michael@0: michael@0: // first run with startup crash tracking - existing profile lock michael@0: let replacedLockTime = Date.now(); michael@0: resetTestEnv(replacedLockTime); michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_false(prefService.prefHasUserValue(pref_last_success)); michael@0: do_check_eq(replacedLockTime, gAppInfo.replacedLockTime); michael@0: try { michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: do_throw("Should have thrown since last_success is not set"); michael@0: } catch (x) { } michael@0: michael@0: do_check_false(prefService.prefHasUserValue(pref_last_success)); michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // first run with startup crash tracking - no existing profile lock michael@0: replacedLockTime = 0; michael@0: resetTestEnv(replacedLockTime); michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_false(prefService.prefHasUserValue(pref_last_success)); michael@0: do_check_eq(replacedLockTime, gAppInfo.replacedLockTime); michael@0: try { michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: do_throw("Should have thrown since last_success is not set"); michael@0: } catch (x) { } michael@0: michael@0: do_check_false(prefService.prefHasUserValue(pref_last_success)); michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // normal startup - last startup was success michael@0: replacedLockTime = Date.now(); michael@0: resetTestEnv(replacedLockTime); michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); michael@0: do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // normal startup with 1 recent crash michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_recent_crashes, 1); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); michael@0: do_check_eq(1, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // normal startup with max_resumed_crashes crash michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_recent_crashes, max_resumed); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); michael@0: do_check_eq(max_resumed, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // normal startup with too many recent crashes michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_recent_crashes, max_resumed + 1); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); michael@0: do_check_true(appStartup.trackStartupCrashBegin()); michael@0: // should remain the same since the last startup was not a crash michael@0: do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_true(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // normal startup with too many recent crashes and startup crash tracking disabled michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_max_resumed_crashes, -1); michael@0: prefService.setIntPref(pref_recent_crashes, max_resumed + 1); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: // should remain the same since the last startup was not a crash michael@0: do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); michael@0: // returns false when disabled michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: do_check_eq(-1, prefService.getIntPref(pref_max_resumed_crashes)); michael@0: michael@0: // normal startup after 1 non-recent crash (1 year ago), no other recent michael@0: replacedLockTime = Date.now() - 365 * 24 * 60 * 60 * 1000; michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 365 * 24 * 60 * 60); michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: // recent crash count pref should be unset since the last crash was not recent michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // normal startup after 1 crash (1 minute ago), no other recent michael@0: replacedLockTime = Date.now() - 60 * 1000; michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: // recent crash count pref should be created with value 1 michael@0: do_check_eq(1, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // normal startup after another crash (1 minute ago), 1 already michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago michael@0: replacedLockTime = Date.now() - 60 * 1000; michael@0: gAppInfo.replacedLockTime = replacedLockTime; michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: // recent crash count pref should be incremented by 1 michael@0: do_check_eq(2, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // normal startup after another crash (1 minute ago), 2 already michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago michael@0: do_check_true(appStartup.trackStartupCrashBegin()); michael@0: // recent crash count pref should be incremented by 1 michael@0: do_check_eq(3, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_true(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // normal startup after 1 non-recent crash (1 year ago), 3 crashes already michael@0: replacedLockTime = Date.now() - 365 * 24 * 60 * 60 * 1000; michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: // recent crash count should be unset since the last crash was not recent michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: } michael@0: michael@0: function test_trackStartupCrashEnd() { michael@0: // successful startup with no last_success (upgrade test) michael@0: let replacedLockTime = Date.now() - 10 * 1000; // 10s ago michael@0: resetTestEnv(replacedLockTime); michael@0: try { michael@0: appStartup.trackStartupCrashBegin(); // required to be called before end michael@0: do_throw("Should have thrown since last_success is not set"); michael@0: } catch (x) { } michael@0: appStartup.trackStartupCrashEnd(); michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_false(prefService.prefHasUserValue(pref_last_success)); michael@0: michael@0: // successful startup - should set last_success michael@0: replacedLockTime = Date.now() - 10 * 1000; // 10s ago michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); michael@0: appStartup.trackStartupCrashBegin(); // required to be called before end michael@0: appStartup.trackStartupCrashEnd(); michael@0: // ensure last_success was set since we have declared a succesful startup michael@0: // main timestamp doesn't get set in XPCShell so approximate with now michael@0: do_check_true(prefService.getIntPref(pref_last_success) <= now_seconds()); michael@0: do_check_true(prefService.getIntPref(pref_last_success) >= now_seconds() - 4 * 60 * 60); michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: michael@0: // successful startup with 1 recent crash michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); michael@0: prefService.setIntPref(pref_recent_crashes, 1); michael@0: appStartup.trackStartupCrashBegin(); // required to be called before end michael@0: appStartup.trackStartupCrashEnd(); michael@0: // ensure recent_crashes was cleared since we have declared a succesful startup michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: } michael@0: michael@0: function test_trackStartupCrashBegin_safeMode() { michael@0: gAppInfo.inSafeMode = true; michael@0: resetTestEnv(0); michael@0: let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); michael@0: michael@0: // check manual safe mode doesn't change prefs without crash michael@0: let replacedLockTime = Date.now() - 10 * 1000; // 10s ago michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); michael@0: michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_true(prefService.prefHasUserValue(pref_last_success)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: do_check_false(appStartup.trackStartupCrashBegin()); michael@0: do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); michael@0: do_check_true(prefService.prefHasUserValue(pref_last_success)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // check forced safe mode doesn't change prefs without crash michael@0: replacedLockTime = Date.now() - 10 * 1000; // 10s ago michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); michael@0: prefService.setIntPref(pref_recent_crashes, max_resumed + 1); michael@0: michael@0: do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_true(prefService.prefHasUserValue(pref_last_success)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: do_check_true(appStartup.trackStartupCrashBegin()); michael@0: do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_true(prefService.prefHasUserValue(pref_last_success)); michael@0: do_check_true(appStartup.automaticSafeModeNecessary); michael@0: michael@0: // check forced safe mode after old crash michael@0: replacedLockTime = Date.now() - 365 * 24 * 60 * 60 * 1000; michael@0: resetTestEnv(replacedLockTime); michael@0: // one year ago michael@0: let last_success = ms_to_s(replacedLockTime) - 365 * 24 * 60 * 60; michael@0: prefService.setIntPref(pref_last_success, last_success); michael@0: prefService.setIntPref(pref_recent_crashes, max_resumed + 1); michael@0: do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_true(prefService.prefHasUserValue(pref_last_success)); michael@0: do_check_true(appStartup.automaticSafeModeNecessary); michael@0: do_check_true(appStartup.trackStartupCrashBegin()); michael@0: do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_eq(last_success, prefService.getIntPref(pref_last_success)); michael@0: do_check_true(appStartup.automaticSafeModeNecessary); michael@0: } michael@0: michael@0: function test_trackStartupCrashEnd_safeMode() { michael@0: gAppInfo.inSafeMode = true; michael@0: let replacedLockTime = Date.now(); michael@0: resetTestEnv(replacedLockTime); michael@0: let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 24 * 60 * 60); michael@0: michael@0: // ensure recent_crashes were not cleared in manual safe mode michael@0: prefService.setIntPref(pref_recent_crashes, 1); michael@0: appStartup.trackStartupCrashBegin(); // required to be called before end michael@0: appStartup.trackStartupCrashEnd(); michael@0: do_check_eq(1, prefService.getIntPref(pref_recent_crashes)); michael@0: michael@0: // recent_crashes should be set to max_resumed in forced safe mode to allow the user michael@0: // to try and start in regular mode after making changes. michael@0: prefService.setIntPref(pref_recent_crashes, max_resumed + 1); michael@0: appStartup.trackStartupCrashBegin(); // required to be called before end michael@0: appStartup.trackStartupCrashEnd(); michael@0: do_check_eq(max_resumed, prefService.getIntPref(pref_recent_crashes)); michael@0: } michael@0: michael@0: function test_maxResumed() { michael@0: resetTestEnv(0); michael@0: gAppInfo.inSafeMode = false; michael@0: let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); michael@0: let replacedLockTime = Date.now(); michael@0: resetTestEnv(replacedLockTime); michael@0: prefService.setIntPref(pref_max_resumed_crashes, -1); michael@0: michael@0: prefService.setIntPref(pref_recent_crashes, max_resumed + 1); michael@0: prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 24 * 60 * 60); michael@0: appStartup.trackStartupCrashBegin(); michael@0: // should remain the same since the last startup was not a crash michael@0: do_check_eq(max_resumed + 2, prefService.getIntPref(pref_recent_crashes)); michael@0: do_check_false(appStartup.automaticSafeModeNecessary); michael@0: }