|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 Components.utils.import("resource://gre/modules/Services.jsm"); |
|
5 |
|
6 const Cc = Components.classes; |
|
7 const Ci = Components.interfaces; |
|
8 |
|
9 createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "10.0"); |
|
10 |
|
11 let prefService = Services.prefs; |
|
12 let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]. |
|
13 getService(Ci.nsIAppStartup); |
|
14 |
|
15 const pref_last_success = "toolkit.startup.last_success"; |
|
16 const pref_recent_crashes = "toolkit.startup.recent_crashes"; |
|
17 const pref_max_resumed_crashes = "toolkit.startup.max_resumed_crashes"; |
|
18 const pref_always_use_safe_mode = "toolkit.startup.always_use_safe_mode"; |
|
19 |
|
20 function run_test() { |
|
21 prefService.setBoolPref(pref_always_use_safe_mode, true); |
|
22 |
|
23 resetTestEnv(0); |
|
24 |
|
25 test_trackStartupCrashBegin(); |
|
26 test_trackStartupCrashEnd(); |
|
27 test_trackStartupCrashBegin_safeMode(); |
|
28 test_trackStartupCrashEnd_safeMode(); |
|
29 test_maxResumed(); |
|
30 resetTestEnv(0); |
|
31 |
|
32 prefService.clearUserPref(pref_always_use_safe_mode); |
|
33 } |
|
34 |
|
35 // reset prefs to default |
|
36 function resetTestEnv(replacedLockTime) { |
|
37 try { |
|
38 // call begin to reset mStartupCrashTrackingEnded |
|
39 appStartup.trackStartupCrashBegin(); |
|
40 } catch (x) { } |
|
41 prefService.setIntPref(pref_max_resumed_crashes, 2); |
|
42 prefService.clearUserPref(pref_recent_crashes); |
|
43 gAppInfo.replacedLockTime = replacedLockTime; |
|
44 prefService.clearUserPref(pref_last_success); |
|
45 } |
|
46 |
|
47 function now_seconds() { |
|
48 return ms_to_s(Date.now()); |
|
49 } |
|
50 |
|
51 function ms_to_s(ms) { |
|
52 return Math.floor(ms / 1000); |
|
53 } |
|
54 |
|
55 function test_trackStartupCrashBegin() { |
|
56 let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); |
|
57 do_check_false(gAppInfo.inSafeMode); |
|
58 |
|
59 // first run with startup crash tracking - existing profile lock |
|
60 let replacedLockTime = Date.now(); |
|
61 resetTestEnv(replacedLockTime); |
|
62 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
63 do_check_false(prefService.prefHasUserValue(pref_last_success)); |
|
64 do_check_eq(replacedLockTime, gAppInfo.replacedLockTime); |
|
65 try { |
|
66 do_check_false(appStartup.trackStartupCrashBegin()); |
|
67 do_throw("Should have thrown since last_success is not set"); |
|
68 } catch (x) { } |
|
69 |
|
70 do_check_false(prefService.prefHasUserValue(pref_last_success)); |
|
71 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
72 do_check_false(appStartup.automaticSafeModeNecessary); |
|
73 |
|
74 // first run with startup crash tracking - no existing profile lock |
|
75 replacedLockTime = 0; |
|
76 resetTestEnv(replacedLockTime); |
|
77 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
78 do_check_false(prefService.prefHasUserValue(pref_last_success)); |
|
79 do_check_eq(replacedLockTime, gAppInfo.replacedLockTime); |
|
80 try { |
|
81 do_check_false(appStartup.trackStartupCrashBegin()); |
|
82 do_throw("Should have thrown since last_success is not set"); |
|
83 } catch (x) { } |
|
84 |
|
85 do_check_false(prefService.prefHasUserValue(pref_last_success)); |
|
86 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
87 do_check_false(appStartup.automaticSafeModeNecessary); |
|
88 |
|
89 // normal startup - last startup was success |
|
90 replacedLockTime = Date.now(); |
|
91 resetTestEnv(replacedLockTime); |
|
92 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
93 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); |
|
94 do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); |
|
95 do_check_false(appStartup.trackStartupCrashBegin()); |
|
96 do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); |
|
97 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
98 do_check_false(appStartup.automaticSafeModeNecessary); |
|
99 |
|
100 // normal startup with 1 recent crash |
|
101 resetTestEnv(replacedLockTime); |
|
102 prefService.setIntPref(pref_recent_crashes, 1); |
|
103 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); |
|
104 do_check_false(appStartup.trackStartupCrashBegin()); |
|
105 do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); |
|
106 do_check_eq(1, prefService.getIntPref(pref_recent_crashes)); |
|
107 do_check_false(appStartup.automaticSafeModeNecessary); |
|
108 |
|
109 // normal startup with max_resumed_crashes crash |
|
110 resetTestEnv(replacedLockTime); |
|
111 prefService.setIntPref(pref_recent_crashes, max_resumed); |
|
112 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); |
|
113 do_check_false(appStartup.trackStartupCrashBegin()); |
|
114 do_check_eq(ms_to_s(replacedLockTime), prefService.getIntPref(pref_last_success)); |
|
115 do_check_eq(max_resumed, prefService.getIntPref(pref_recent_crashes)); |
|
116 do_check_false(appStartup.automaticSafeModeNecessary); |
|
117 |
|
118 // normal startup with too many recent crashes |
|
119 resetTestEnv(replacedLockTime); |
|
120 prefService.setIntPref(pref_recent_crashes, max_resumed + 1); |
|
121 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); |
|
122 do_check_true(appStartup.trackStartupCrashBegin()); |
|
123 // should remain the same since the last startup was not a crash |
|
124 do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); |
|
125 do_check_true(appStartup.automaticSafeModeNecessary); |
|
126 |
|
127 // normal startup with too many recent crashes and startup crash tracking disabled |
|
128 resetTestEnv(replacedLockTime); |
|
129 prefService.setIntPref(pref_max_resumed_crashes, -1); |
|
130 prefService.setIntPref(pref_recent_crashes, max_resumed + 1); |
|
131 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); |
|
132 do_check_false(appStartup.trackStartupCrashBegin()); |
|
133 // should remain the same since the last startup was not a crash |
|
134 do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); |
|
135 // returns false when disabled |
|
136 do_check_false(appStartup.automaticSafeModeNecessary); |
|
137 do_check_eq(-1, prefService.getIntPref(pref_max_resumed_crashes)); |
|
138 |
|
139 // normal startup after 1 non-recent crash (1 year ago), no other recent |
|
140 replacedLockTime = Date.now() - 365 * 24 * 60 * 60 * 1000; |
|
141 resetTestEnv(replacedLockTime); |
|
142 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 365 * 24 * 60 * 60); |
|
143 do_check_false(appStartup.trackStartupCrashBegin()); |
|
144 // recent crash count pref should be unset since the last crash was not recent |
|
145 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
146 do_check_false(appStartup.automaticSafeModeNecessary); |
|
147 |
|
148 // normal startup after 1 crash (1 minute ago), no other recent |
|
149 replacedLockTime = Date.now() - 60 * 1000; |
|
150 resetTestEnv(replacedLockTime); |
|
151 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago |
|
152 do_check_false(appStartup.trackStartupCrashBegin()); |
|
153 // recent crash count pref should be created with value 1 |
|
154 do_check_eq(1, prefService.getIntPref(pref_recent_crashes)); |
|
155 do_check_false(appStartup.automaticSafeModeNecessary); |
|
156 |
|
157 // normal startup after another crash (1 minute ago), 1 already |
|
158 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago |
|
159 replacedLockTime = Date.now() - 60 * 1000; |
|
160 gAppInfo.replacedLockTime = replacedLockTime; |
|
161 do_check_false(appStartup.trackStartupCrashBegin()); |
|
162 // recent crash count pref should be incremented by 1 |
|
163 do_check_eq(2, prefService.getIntPref(pref_recent_crashes)); |
|
164 do_check_false(appStartup.automaticSafeModeNecessary); |
|
165 |
|
166 // normal startup after another crash (1 minute ago), 2 already |
|
167 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago |
|
168 do_check_true(appStartup.trackStartupCrashBegin()); |
|
169 // recent crash count pref should be incremented by 1 |
|
170 do_check_eq(3, prefService.getIntPref(pref_recent_crashes)); |
|
171 do_check_true(appStartup.automaticSafeModeNecessary); |
|
172 |
|
173 // normal startup after 1 non-recent crash (1 year ago), 3 crashes already |
|
174 replacedLockTime = Date.now() - 365 * 24 * 60 * 60 * 1000; |
|
175 resetTestEnv(replacedLockTime); |
|
176 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 60 * 60); // last success - 1 hour ago |
|
177 do_check_false(appStartup.trackStartupCrashBegin()); |
|
178 // recent crash count should be unset since the last crash was not recent |
|
179 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
180 do_check_false(appStartup.automaticSafeModeNecessary); |
|
181 } |
|
182 |
|
183 function test_trackStartupCrashEnd() { |
|
184 // successful startup with no last_success (upgrade test) |
|
185 let replacedLockTime = Date.now() - 10 * 1000; // 10s ago |
|
186 resetTestEnv(replacedLockTime); |
|
187 try { |
|
188 appStartup.trackStartupCrashBegin(); // required to be called before end |
|
189 do_throw("Should have thrown since last_success is not set"); |
|
190 } catch (x) { } |
|
191 appStartup.trackStartupCrashEnd(); |
|
192 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
193 do_check_false(prefService.prefHasUserValue(pref_last_success)); |
|
194 |
|
195 // successful startup - should set last_success |
|
196 replacedLockTime = Date.now() - 10 * 1000; // 10s ago |
|
197 resetTestEnv(replacedLockTime); |
|
198 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); |
|
199 appStartup.trackStartupCrashBegin(); // required to be called before end |
|
200 appStartup.trackStartupCrashEnd(); |
|
201 // ensure last_success was set since we have declared a succesful startup |
|
202 // main timestamp doesn't get set in XPCShell so approximate with now |
|
203 do_check_true(prefService.getIntPref(pref_last_success) <= now_seconds()); |
|
204 do_check_true(prefService.getIntPref(pref_last_success) >= now_seconds() - 4 * 60 * 60); |
|
205 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
206 |
|
207 // successful startup with 1 recent crash |
|
208 resetTestEnv(replacedLockTime); |
|
209 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); |
|
210 prefService.setIntPref(pref_recent_crashes, 1); |
|
211 appStartup.trackStartupCrashBegin(); // required to be called before end |
|
212 appStartup.trackStartupCrashEnd(); |
|
213 // ensure recent_crashes was cleared since we have declared a succesful startup |
|
214 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
215 } |
|
216 |
|
217 function test_trackStartupCrashBegin_safeMode() { |
|
218 gAppInfo.inSafeMode = true; |
|
219 resetTestEnv(0); |
|
220 let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); |
|
221 |
|
222 // check manual safe mode doesn't change prefs without crash |
|
223 let replacedLockTime = Date.now() - 10 * 1000; // 10s ago |
|
224 resetTestEnv(replacedLockTime); |
|
225 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); |
|
226 |
|
227 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
228 do_check_true(prefService.prefHasUserValue(pref_last_success)); |
|
229 do_check_false(appStartup.automaticSafeModeNecessary); |
|
230 do_check_false(appStartup.trackStartupCrashBegin()); |
|
231 do_check_false(prefService.prefHasUserValue(pref_recent_crashes)); |
|
232 do_check_true(prefService.prefHasUserValue(pref_last_success)); |
|
233 do_check_false(appStartup.automaticSafeModeNecessary); |
|
234 |
|
235 // check forced safe mode doesn't change prefs without crash |
|
236 replacedLockTime = Date.now() - 10 * 1000; // 10s ago |
|
237 resetTestEnv(replacedLockTime); |
|
238 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime)); |
|
239 prefService.setIntPref(pref_recent_crashes, max_resumed + 1); |
|
240 |
|
241 do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); |
|
242 do_check_true(prefService.prefHasUserValue(pref_last_success)); |
|
243 do_check_false(appStartup.automaticSafeModeNecessary); |
|
244 do_check_true(appStartup.trackStartupCrashBegin()); |
|
245 do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); |
|
246 do_check_true(prefService.prefHasUserValue(pref_last_success)); |
|
247 do_check_true(appStartup.automaticSafeModeNecessary); |
|
248 |
|
249 // check forced safe mode after old crash |
|
250 replacedLockTime = Date.now() - 365 * 24 * 60 * 60 * 1000; |
|
251 resetTestEnv(replacedLockTime); |
|
252 // one year ago |
|
253 let last_success = ms_to_s(replacedLockTime) - 365 * 24 * 60 * 60; |
|
254 prefService.setIntPref(pref_last_success, last_success); |
|
255 prefService.setIntPref(pref_recent_crashes, max_resumed + 1); |
|
256 do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); |
|
257 do_check_true(prefService.prefHasUserValue(pref_last_success)); |
|
258 do_check_true(appStartup.automaticSafeModeNecessary); |
|
259 do_check_true(appStartup.trackStartupCrashBegin()); |
|
260 do_check_eq(max_resumed + 1, prefService.getIntPref(pref_recent_crashes)); |
|
261 do_check_eq(last_success, prefService.getIntPref(pref_last_success)); |
|
262 do_check_true(appStartup.automaticSafeModeNecessary); |
|
263 } |
|
264 |
|
265 function test_trackStartupCrashEnd_safeMode() { |
|
266 gAppInfo.inSafeMode = true; |
|
267 let replacedLockTime = Date.now(); |
|
268 resetTestEnv(replacedLockTime); |
|
269 let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); |
|
270 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 24 * 60 * 60); |
|
271 |
|
272 // ensure recent_crashes were not cleared in manual safe mode |
|
273 prefService.setIntPref(pref_recent_crashes, 1); |
|
274 appStartup.trackStartupCrashBegin(); // required to be called before end |
|
275 appStartup.trackStartupCrashEnd(); |
|
276 do_check_eq(1, prefService.getIntPref(pref_recent_crashes)); |
|
277 |
|
278 // recent_crashes should be set to max_resumed in forced safe mode to allow the user |
|
279 // to try and start in regular mode after making changes. |
|
280 prefService.setIntPref(pref_recent_crashes, max_resumed + 1); |
|
281 appStartup.trackStartupCrashBegin(); // required to be called before end |
|
282 appStartup.trackStartupCrashEnd(); |
|
283 do_check_eq(max_resumed, prefService.getIntPref(pref_recent_crashes)); |
|
284 } |
|
285 |
|
286 function test_maxResumed() { |
|
287 resetTestEnv(0); |
|
288 gAppInfo.inSafeMode = false; |
|
289 let max_resumed = prefService.getIntPref(pref_max_resumed_crashes); |
|
290 let replacedLockTime = Date.now(); |
|
291 resetTestEnv(replacedLockTime); |
|
292 prefService.setIntPref(pref_max_resumed_crashes, -1); |
|
293 |
|
294 prefService.setIntPref(pref_recent_crashes, max_resumed + 1); |
|
295 prefService.setIntPref(pref_last_success, ms_to_s(replacedLockTime) - 24 * 60 * 60); |
|
296 appStartup.trackStartupCrashBegin(); |
|
297 // should remain the same since the last startup was not a crash |
|
298 do_check_eq(max_resumed + 2, prefService.getIntPref(pref_recent_crashes)); |
|
299 do_check_false(appStartup.automaticSafeModeNecessary); |
|
300 } |