1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/toolkit/components/startup/tests/unit/test_startup_crash.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,300 @@ 1.4 +/* Any copyright is dedicated to the Public Domain. 1.5 + http://creativecommons.org/publicdomain/zero/1.0/ */ 1.6 + 1.7 +Components.utils.import("resource://gre/modules/Services.jsm"); 1.8 + 1.9 +const Cc = Components.classes; 1.10 +const Ci = Components.interfaces; 1.11 + 1.12 +createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "10.0"); 1.13 + 1.14 +let prefService = Services.prefs; 1.15 +let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]. 1.16 + getService(Ci.nsIAppStartup); 1.17 + 1.18 +const pref_last_success = "toolkit.startup.last_success"; 1.19 +const pref_recent_crashes = "toolkit.startup.recent_crashes"; 1.20 +const pref_max_resumed_crashes = "toolkit.startup.max_resumed_crashes"; 1.21 +const pref_always_use_safe_mode = "toolkit.startup.always_use_safe_mode"; 1.22 + 1.23 +function run_test() { 1.24 + prefService.setBoolPref(pref_always_use_safe_mode, true); 1.25 + 1.26 + resetTestEnv(0); 1.27 + 1.28 + test_trackStartupCrashBegin(); 1.29 + test_trackStartupCrashEnd(); 1.30 + test_trackStartupCrashBegin_safeMode(); 1.31 + test_trackStartupCrashEnd_safeMode(); 1.32 + test_maxResumed(); 1.33 + resetTestEnv(0); 1.34 + 1.35 + prefService.clearUserPref(pref_always_use_safe_mode); 1.36 +} 1.37 + 1.38 +// reset prefs to default 1.39 +function resetTestEnv(replacedLockTime) { 1.40 + try { 1.41 + // call begin to reset mStartupCrashTrackingEnded 1.42 + appStartup.trackStartupCrashBegin(); 1.43 + } catch (x) { } 1.44 + prefService.setIntPref(pref_max_resumed_crashes, 2); 1.45 + prefService.clearUserPref(pref_recent_crashes); 1.46 + gAppInfo.replacedLockTime = replacedLockTime; 1.47 + prefService.clearUserPref(pref_last_success); 1.48 +} 1.49 + 1.50 +function now_seconds() { 1.51 + return ms_to_s(Date.now()); 1.52 +} 1.53 + 1.54 +function ms_to_s(ms) { 1.55 + return Math.floor(ms / 1000); 1.56 +} 1.57 + 1.58 +function test_trackStartupCrashBegin() { 1.59 + let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); 1.60 + do_check_false(gAppInfo.inSafeMode); 1.61 + 1.62 + // first run with startup crash tracking - existing profile lock 1.63 + let replacedLockTime = Date.now(); 1.64 + resetTestEnv(replacedLockTime); 1.65 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.66 + do_check_false(prefService.prefHasUserValue(pref_last_success)); 1.67 + do_check_eq(replacedLockTime, gAppInfo.replacedLockTime); 1.68 + try { 1.69 + do_check_false(appStartup.trackStartupCrashBegin()); 1.70 + do_throw("Should have thrown since last_success is not set"); 1.71 + } catch (x) { } 1.72 + 1.73 + do_check_false(prefService.prefHasUserValue(pref_last_success)); 1.74 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.75 + do_check_false(appStartup.automaticSafeModeNecessary); 1.76 + 1.77 + // first run with startup crash tracking - no existing profile lock 1.78 + replacedLockTime = 0; 1.79 + resetTestEnv(replacedLockTime); 1.80 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.81 + do_check_false(prefService.prefHasUserValue(pref_last_success)); 1.82 + do_check_eq(replacedLockTime, gAppInfo.replacedLockTime); 1.83 + try { 1.84 + do_check_false(appStartup.trackStartupCrashBegin()); 1.85 + do_throw("Should have thrown since last_success is not set"); 1.86 + } catch (x) { } 1.87 + 1.88 + do_check_false(prefService.prefHasUserValue(pref_last_success)); 1.89 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.90 + do_check_false(appStartup.automaticSafeModeNecessary); 1.91 + 1.92 + // normal startup - last startup was success 1.93 + replacedLockTime = Date.now(); 1.94 + resetTestEnv(replacedLockTime); 1.95 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.96 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); 1.97 + do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); 1.98 + do_check_false(appStartup.trackStartupCrashBegin()); 1.99 + do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); 1.100 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.101 + do_check_false(appStartup.automaticSafeModeNecessary); 1.102 + 1.103 + // normal startup with 1 recent crash 1.104 + resetTestEnv(replacedLockTime); 1.105 + prefService.setIntPref(pref_recent_crashes, 1); 1.106 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); 1.107 + do_check_false(appStartup.trackStartupCrashBegin()); 1.108 + do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); 1.109 + do_check_eq(1, prefService.getIntPref(pref_recent_crashes)); 1.110 + do_check_false(appStartup.automaticSafeModeNecessary); 1.111 + 1.112 + // normal startup with max_resumed_crashes crash 1.113 + resetTestEnv(replacedLockTime); 1.114 + prefService.setIntPref(pref_recent_crashes, max_resumed); 1.115 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); 1.116 + do_check_false(appStartup.trackStartupCrashBegin()); 1.117 + do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); 1.118 + do_check_eq(max_resumed, prefService.getIntPref(pref_recent_crashes)); 1.119 + do_check_false(appStartup.automaticSafeModeNecessary); 1.120 + 1.121 + // normal startup with too many recent crashes 1.122 + resetTestEnv(replacedLockTime); 1.123 + prefService.setIntPref(pref_recent_crashes, max_resumed + 1); 1.124 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); 1.125 + do_check_true(appStartup.trackStartupCrashBegin()); 1.126 + // should remain the same since the last startup was not a crash 1.127 + do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); 1.128 + do_check_true(appStartup.automaticSafeModeNecessary); 1.129 + 1.130 + // normal startup with too many recent crashes and startup crash tracking disabled 1.131 + resetTestEnv(replacedLockTime); 1.132 + prefService.setIntPref(pref_max_resumed_crashes, -1); 1.133 + prefService.setIntPref(pref_recent_crashes, max_resumed + 1); 1.134 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); 1.135 + do_check_false(appStartup.trackStartupCrashBegin()); 1.136 + // should remain the same since the last startup was not a crash 1.137 + do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); 1.138 + // returns false when disabled 1.139 + do_check_false(appStartup.automaticSafeModeNecessary); 1.140 + do_check_eq(-1, prefService.getIntPref(pref_max_resumed_crashes)); 1.141 + 1.142 + // normal startup after 1 non-recent crash (1 year ago), no other recent 1.143 + replacedLockTime = Date.now() - 365 * 24 * 60 * 60 * 1000; 1.144 + resetTestEnv(replacedLockTime); 1.145 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 365 * 24 * 60 * 60); 1.146 + do_check_false(appStartup.trackStartupCrashBegin()); 1.147 + // recent crash count pref should be unset since the last crash was not recent 1.148 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.149 + do_check_false(appStartup.automaticSafeModeNecessary); 1.150 + 1.151 + // normal startup after 1 crash (1 minute ago), no other recent 1.152 + replacedLockTime = Date.now() - 60 * 1000; 1.153 + resetTestEnv(replacedLockTime); 1.154 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago 1.155 + do_check_false(appStartup.trackStartupCrashBegin()); 1.156 + // recent crash count pref should be created with value 1 1.157 + do_check_eq(1, prefService.getIntPref(pref_recent_crashes)); 1.158 + do_check_false(appStartup.automaticSafeModeNecessary); 1.159 + 1.160 + // normal startup after another crash (1 minute ago), 1 already 1.161 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago 1.162 + replacedLockTime = Date.now() - 60 * 1000; 1.163 + gAppInfo.replacedLockTime = replacedLockTime; 1.164 + do_check_false(appStartup.trackStartupCrashBegin()); 1.165 + // recent crash count pref should be incremented by 1 1.166 + do_check_eq(2, prefService.getIntPref(pref_recent_crashes)); 1.167 + do_check_false(appStartup.automaticSafeModeNecessary); 1.168 + 1.169 + // normal startup after another crash (1 minute ago), 2 already 1.170 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago 1.171 + do_check_true(appStartup.trackStartupCrashBegin()); 1.172 + // recent crash count pref should be incremented by 1 1.173 + do_check_eq(3, prefService.getIntPref(pref_recent_crashes)); 1.174 + do_check_true(appStartup.automaticSafeModeNecessary); 1.175 + 1.176 + // normal startup after 1 non-recent crash (1 year ago), 3 crashes already 1.177 + replacedLockTime = Date.now() - 365 * 24 * 60 * 60 * 1000; 1.178 + resetTestEnv(replacedLockTime); 1.179 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago 1.180 + do_check_false(appStartup.trackStartupCrashBegin()); 1.181 + // recent crash count should be unset since the last crash was not recent 1.182 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.183 + do_check_false(appStartup.automaticSafeModeNecessary); 1.184 +} 1.185 + 1.186 +function test_trackStartupCrashEnd() { 1.187 + // successful startup with no last_success (upgrade test) 1.188 + let replacedLockTime = Date.now() - 10 * 1000; // 10s ago 1.189 + resetTestEnv(replacedLockTime); 1.190 + try { 1.191 + appStartup.trackStartupCrashBegin(); // required to be called before end 1.192 + do_throw("Should have thrown since last_success is not set"); 1.193 + } catch (x) { } 1.194 + appStartup.trackStartupCrashEnd(); 1.195 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.196 + do_check_false(prefService.prefHasUserValue(pref_last_success)); 1.197 + 1.198 + // successful startup - should set last_success 1.199 + replacedLockTime = Date.now() - 10 * 1000; // 10s ago 1.200 + resetTestEnv(replacedLockTime); 1.201 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); 1.202 + appStartup.trackStartupCrashBegin(); // required to be called before end 1.203 + appStartup.trackStartupCrashEnd(); 1.204 + // ensure last_success was set since we have declared a succesful startup 1.205 + // main timestamp doesn't get set in XPCShell so approximate with now 1.206 + do_check_true(prefService.getIntPref(pref_last_success) <= now_seconds()); 1.207 + do_check_true(prefService.getIntPref(pref_last_success) >= now_seconds() - 4 * 60 * 60); 1.208 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.209 + 1.210 + // successful startup with 1 recent crash 1.211 + resetTestEnv(replacedLockTime); 1.212 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); 1.213 + prefService.setIntPref(pref_recent_crashes, 1); 1.214 + appStartup.trackStartupCrashBegin(); // required to be called before end 1.215 + appStartup.trackStartupCrashEnd(); 1.216 + // ensure recent_crashes was cleared since we have declared a succesful startup 1.217 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.218 +} 1.219 + 1.220 +function test_trackStartupCrashBegin_safeMode() { 1.221 + gAppInfo.inSafeMode = true; 1.222 + resetTestEnv(0); 1.223 + let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); 1.224 + 1.225 + // check manual safe mode doesn't change prefs without crash 1.226 + let replacedLockTime = Date.now() - 10 * 1000; // 10s ago 1.227 + resetTestEnv(replacedLockTime); 1.228 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); 1.229 + 1.230 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.231 + do_check_true(prefService.prefHasUserValue(pref_last_success)); 1.232 + do_check_false(appStartup.automaticSafeModeNecessary); 1.233 + do_check_false(appStartup.trackStartupCrashBegin()); 1.234 + do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); 1.235 + do_check_true(prefService.prefHasUserValue(pref_last_success)); 1.236 + do_check_false(appStartup.automaticSafeModeNecessary); 1.237 + 1.238 + // check forced safe mode doesn't change prefs without crash 1.239 + replacedLockTime = Date.now() - 10 * 1000; // 10s ago 1.240 + resetTestEnv(replacedLockTime); 1.241 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); 1.242 + prefService.setIntPref(pref_recent_crashes, max_resumed + 1); 1.243 + 1.244 + do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); 1.245 + do_check_true(prefService.prefHasUserValue(pref_last_success)); 1.246 + do_check_false(appStartup.automaticSafeModeNecessary); 1.247 + do_check_true(appStartup.trackStartupCrashBegin()); 1.248 + do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); 1.249 + do_check_true(prefService.prefHasUserValue(pref_last_success)); 1.250 + do_check_true(appStartup.automaticSafeModeNecessary); 1.251 + 1.252 + // check forced safe mode after old crash 1.253 + replacedLockTime = Date.now() - 365 * 24 * 60 * 60 * 1000; 1.254 + resetTestEnv(replacedLockTime); 1.255 + // one year ago 1.256 + let last_success = ms_to_s(replacedLockTime) - 365 * 24 * 60 * 60; 1.257 + prefService.setIntPref(pref_last_success, last_success); 1.258 + prefService.setIntPref(pref_recent_crashes, max_resumed + 1); 1.259 + do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); 1.260 + do_check_true(prefService.prefHasUserValue(pref_last_success)); 1.261 + do_check_true(appStartup.automaticSafeModeNecessary); 1.262 + do_check_true(appStartup.trackStartupCrashBegin()); 1.263 + do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); 1.264 + do_check_eq(last_success, prefService.getIntPref(pref_last_success)); 1.265 + do_check_true(appStartup.automaticSafeModeNecessary); 1.266 +} 1.267 + 1.268 +function test_trackStartupCrashEnd_safeMode() { 1.269 + gAppInfo.inSafeMode = true; 1.270 + let replacedLockTime = Date.now(); 1.271 + resetTestEnv(replacedLockTime); 1.272 + let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); 1.273 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 24 * 60 * 60); 1.274 + 1.275 + // ensure recent_crashes were not cleared in manual safe mode 1.276 + prefService.setIntPref(pref_recent_crashes, 1); 1.277 + appStartup.trackStartupCrashBegin(); // required to be called before end 1.278 + appStartup.trackStartupCrashEnd(); 1.279 + do_check_eq(1, prefService.getIntPref(pref_recent_crashes)); 1.280 + 1.281 + // recent_crashes should be set to max_resumed in forced safe mode to allow the user 1.282 + // to try and start in regular mode after making changes. 1.283 + prefService.setIntPref(pref_recent_crashes, max_resumed + 1); 1.284 + appStartup.trackStartupCrashBegin(); // required to be called before end 1.285 + appStartup.trackStartupCrashEnd(); 1.286 + do_check_eq(max_resumed, prefService.getIntPref(pref_recent_crashes)); 1.287 +} 1.288 + 1.289 +function test_maxResumed() { 1.290 + resetTestEnv(0); 1.291 + gAppInfo.inSafeMode = false; 1.292 + let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); 1.293 + let replacedLockTime = Date.now(); 1.294 + resetTestEnv(replacedLockTime); 1.295 + prefService.setIntPref(pref_max_resumed_crashes, -1); 1.296 + 1.297 + prefService.setIntPref(pref_recent_crashes, max_resumed + 1); 1.298 + prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 24 * 60 * 60); 1.299 + appStartup.trackStartupCrashBegin(); 1.300 + // should remain the same since the last startup was not a crash 1.301 + do_check_eq(max_resumed + 2, prefService.getIntPref(pref_recent_crashes)); 1.302 + do_check_false(appStartup.automaticSafeModeNecessary); 1.303 +} 1.304 \ No newline at end of file