|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 // Test the various ways opening a cookie database can fail in an asynchronous |
|
5 // (i.e. after synchronous initialization) manner, and that the database is |
|
6 // renamed and recreated under each circumstance. These circumstances are, in no |
|
7 // particular order: |
|
8 // |
|
9 // 1) A write operation failing after the database has been read in. |
|
10 // 2) Asynchronous read failure due to a corrupt database. |
|
11 // 3) Synchronous read failure due to a corrupt database, when reading: |
|
12 // a) a single base domain; |
|
13 // b) the entire database. |
|
14 // 4) Asynchronous read failure, followed by another failure during INSERT but |
|
15 // before the database closes for rebuilding. (The additional error should be |
|
16 // ignored.) |
|
17 // 5) Asynchronous read failure, followed by an INSERT failure during rebuild. |
|
18 // This should result in an abort of the database rebuild; the partially- |
|
19 // built database should be moved to 'cookies.sqlite.bak-rebuild'. |
|
20 |
|
21 let test_generator = do_run_test(); |
|
22 |
|
23 function run_test() { |
|
24 do_test_pending(); |
|
25 do_run_generator(test_generator); |
|
26 } |
|
27 |
|
28 function finish_test() { |
|
29 do_execute_soon(function() { |
|
30 test_generator.close(); |
|
31 do_test_finished(); |
|
32 }); |
|
33 } |
|
34 |
|
35 function do_run_test() { |
|
36 // Set up a profile. |
|
37 this.profile = do_get_profile(); |
|
38 |
|
39 // Allow all cookies. |
|
40 Services.prefs.setIntPref("network.cookie.cookieBehavior", 0); |
|
41 |
|
42 // Get the cookie file and the backup file. |
|
43 do_check_false(do_get_cookie_file(profile).exists()); |
|
44 do_check_false(do_get_backup_file(profile).exists()); |
|
45 |
|
46 // Create a cookie object for testing. |
|
47 this.now = Date.now() * 1000; |
|
48 this.futureExpiry = Math.round(this.now / 1e6 + 1000); |
|
49 this.cookie = new Cookie("oh", "hai", "bar.com", "/", this.futureExpiry, |
|
50 this.now, this.now, false, false, false); |
|
51 |
|
52 this.sub_generator = run_test_1(test_generator); |
|
53 sub_generator.next(); |
|
54 yield; |
|
55 |
|
56 this.sub_generator = run_test_2(test_generator); |
|
57 sub_generator.next(); |
|
58 yield; |
|
59 |
|
60 this.sub_generator = run_test_3(test_generator); |
|
61 sub_generator.next(); |
|
62 yield; |
|
63 |
|
64 this.sub_generator = run_test_4(test_generator); |
|
65 sub_generator.next(); |
|
66 yield; |
|
67 |
|
68 this.sub_generator = run_test_5(test_generator); |
|
69 sub_generator.next(); |
|
70 yield; |
|
71 |
|
72 finish_test(); |
|
73 return; |
|
74 } |
|
75 |
|
76 function do_get_backup_file(profile) |
|
77 { |
|
78 let file = profile.clone(); |
|
79 file.append("cookies.sqlite.bak"); |
|
80 return file; |
|
81 } |
|
82 |
|
83 function do_get_rebuild_backup_file(profile) |
|
84 { |
|
85 let file = profile.clone(); |
|
86 file.append("cookies.sqlite.bak-rebuild"); |
|
87 return file; |
|
88 } |
|
89 |
|
90 function do_corrupt_db(file) |
|
91 { |
|
92 // Sanity check: the database size should be larger than 450k, since we've |
|
93 // written about 460k of data. If it's not, let's make it obvious now. |
|
94 let size = file.fileSize; |
|
95 do_check_true(size > 450e3); |
|
96 |
|
97 // Corrupt the database by writing bad data to the end of the file. We |
|
98 // assume that the important metadata -- table structure etc -- is stored |
|
99 // elsewhere, and that doing this will not cause synchronous failure when |
|
100 // initializing the database connection. This is totally empirical -- |
|
101 // overwriting between 1k and 100k of live data seems to work. (Note that the |
|
102 // database file will be larger than the actual content requires, since the |
|
103 // cookie service uses a large growth increment. So we calculate the offset |
|
104 // based on the expected size of the content, not just the file size.) |
|
105 let ostream = Cc["@mozilla.org/network/file-output-stream;1"]. |
|
106 createInstance(Ci.nsIFileOutputStream); |
|
107 ostream.init(file, 2, -1, 0); |
|
108 let sstream = ostream.QueryInterface(Ci.nsISeekableStream); |
|
109 let n = size - 450e3 + 20e3; |
|
110 sstream.seek(Ci.nsISeekableStream.NS_SEEK_SET, size - n); |
|
111 for (let i = 0; i < n; ++i) { |
|
112 ostream.write("a", 1); |
|
113 } |
|
114 ostream.flush(); |
|
115 ostream.close(); |
|
116 |
|
117 do_check_eq(file.clone().fileSize, size); |
|
118 return size; |
|
119 } |
|
120 |
|
121 function run_test_1(generator) |
|
122 { |
|
123 // Load the profile and populate it. |
|
124 let uri = NetUtil.newURI("http://foo.com/"); |
|
125 Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); |
|
126 |
|
127 // Close the profile. |
|
128 do_close_profile(sub_generator); |
|
129 yield; |
|
130 |
|
131 // Open a database connection now, before we load the profile and begin |
|
132 // asynchronous write operations. In order to tell when the async delete |
|
133 // statement has completed, we do something tricky: open a schema 2 connection |
|
134 // and add a cookie with null baseDomain. We can then wait until we see it |
|
135 // deleted in the new database. |
|
136 let db2 = new CookieDatabaseConnection(do_get_cookie_file(profile), 2); |
|
137 db2.db.executeSimpleSQL("INSERT INTO moz_cookies (baseDomain) VALUES (NULL)"); |
|
138 db2.close(); |
|
139 let db = new CookieDatabaseConnection(do_get_cookie_file(profile), 4); |
|
140 do_check_eq(do_count_cookies_in_db(db.db), 2); |
|
141 |
|
142 // Load the profile, and wait for async read completion... |
|
143 do_load_profile(sub_generator); |
|
144 yield; |
|
145 |
|
146 // ... and the DELETE statement to finish. |
|
147 while (do_count_cookies_in_db(db.db) == 2) { |
|
148 do_execute_soon(function() { |
|
149 do_run_generator(sub_generator); |
|
150 }); |
|
151 yield; |
|
152 } |
|
153 do_check_eq(do_count_cookies_in_db(db.db), 1); |
|
154 |
|
155 // Insert a row. |
|
156 db.insertCookie(cookie); |
|
157 db.close(); |
|
158 |
|
159 // Attempt to insert a cookie with the same (name, host, path) triplet. |
|
160 Services.cookiemgr.add(cookie.host, cookie.path, cookie.name, "hallo", |
|
161 cookie.isSecure, cookie.isHttpOnly, cookie.isSession, cookie.expiry); |
|
162 |
|
163 // Check that the cookie service accepted the new cookie. |
|
164 do_check_eq(Services.cookiemgr.countCookiesFromHost(cookie.host), 1); |
|
165 |
|
166 // Wait for the cookie service to rename the old database and rebuild. |
|
167 new _observer(sub_generator, "cookie-db-rebuilding"); |
|
168 yield; |
|
169 do_execute_soon(function() { do_run_generator(sub_generator); }); |
|
170 yield; |
|
171 |
|
172 // At this point, the cookies should still be in memory. |
|
173 do_check_eq(Services.cookiemgr.countCookiesFromHost("foo.com"), 1); |
|
174 do_check_eq(Services.cookiemgr.countCookiesFromHost(cookie.host), 1); |
|
175 do_check_eq(do_count_cookies(), 2); |
|
176 |
|
177 // Close the profile. |
|
178 do_close_profile(sub_generator); |
|
179 yield; |
|
180 |
|
181 // Check that the original database was renamed, and that it contains the |
|
182 // original cookie. |
|
183 do_check_true(do_get_backup_file(profile).exists()); |
|
184 let backupdb = Services.storage.openDatabase(do_get_backup_file(profile)); |
|
185 do_check_eq(do_count_cookies_in_db(backupdb, "foo.com"), 1); |
|
186 backupdb.close(); |
|
187 |
|
188 // Load the profile, and check that it contains the new cookie. |
|
189 do_load_profile(); |
|
190 |
|
191 do_check_eq(Services.cookiemgr.countCookiesFromHost("foo.com"), 1); |
|
192 let enumerator = Services.cookiemgr.getCookiesFromHost(cookie.host); |
|
193 do_check_true(enumerator.hasMoreElements()); |
|
194 let dbcookie = enumerator.getNext().QueryInterface(Ci.nsICookie2); |
|
195 do_check_eq(dbcookie.value, "hallo"); |
|
196 do_check_false(enumerator.hasMoreElements()); |
|
197 |
|
198 // Close the profile. |
|
199 do_close_profile(sub_generator); |
|
200 yield; |
|
201 |
|
202 // Clean up. |
|
203 do_get_cookie_file(profile).remove(false); |
|
204 do_get_backup_file(profile).remove(false); |
|
205 do_check_false(do_get_cookie_file(profile).exists()); |
|
206 do_check_false(do_get_backup_file(profile).exists()); |
|
207 do_run_generator(generator); |
|
208 } |
|
209 |
|
210 function run_test_2(generator) |
|
211 { |
|
212 // Load the profile and populate it. |
|
213 do_load_profile(); |
|
214 for (let i = 0; i < 3000; ++i) { |
|
215 let uri = NetUtil.newURI("http://" + i + ".com/"); |
|
216 Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); |
|
217 } |
|
218 |
|
219 // Close the profile. |
|
220 do_close_profile(sub_generator); |
|
221 yield; |
|
222 |
|
223 // Corrupt the database file. |
|
224 let size = do_corrupt_db(do_get_cookie_file(profile)); |
|
225 |
|
226 // Load the profile. |
|
227 do_load_profile(); |
|
228 |
|
229 // At this point, the database connection should be open. Ensure that it |
|
230 // succeeded. |
|
231 do_check_false(do_get_backup_file(profile).exists()); |
|
232 |
|
233 // Synchronously read in the first cookie. This will cause it to go into the |
|
234 // cookie table, whereupon it will be written out during database rebuild. |
|
235 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); |
|
236 |
|
237 // Wait for the asynchronous read to choke, at which point the backup file |
|
238 // will be created and the database rebuilt. |
|
239 new _observer(sub_generator, "cookie-db-rebuilding"); |
|
240 yield; |
|
241 do_execute_soon(function() { do_run_generator(sub_generator); }); |
|
242 yield; |
|
243 |
|
244 // At this point, the cookies should still be in memory. |
|
245 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); |
|
246 do_check_eq(do_count_cookies(), 1); |
|
247 |
|
248 // Close the profile. |
|
249 do_close_profile(sub_generator); |
|
250 yield; |
|
251 |
|
252 // Check that the original database was renamed. |
|
253 do_check_true(do_get_backup_file(profile).exists()); |
|
254 do_check_eq(do_get_backup_file(profile).fileSize, size); |
|
255 let db = Services.storage.openDatabase(do_get_cookie_file(profile)); |
|
256 do_check_eq(do_count_cookies_in_db(db, "0.com"), 1); |
|
257 db.close(); |
|
258 |
|
259 // Load the profile, and check that it contains the new cookie. |
|
260 do_load_profile(); |
|
261 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); |
|
262 do_check_eq(do_count_cookies(), 1); |
|
263 |
|
264 // Close the profile. |
|
265 do_close_profile(sub_generator); |
|
266 yield; |
|
267 |
|
268 // Clean up. |
|
269 do_get_cookie_file(profile).remove(false); |
|
270 do_get_backup_file(profile).remove(false); |
|
271 do_check_false(do_get_cookie_file(profile).exists()); |
|
272 do_check_false(do_get_backup_file(profile).exists()); |
|
273 do_run_generator(generator); |
|
274 } |
|
275 |
|
276 function run_test_3(generator) |
|
277 { |
|
278 // Set the maximum cookies per base domain limit to a large value, so that |
|
279 // corrupting the database is easier. |
|
280 Services.prefs.setIntPref("network.cookie.maxPerHost", 3000); |
|
281 |
|
282 // Load the profile and populate it. |
|
283 do_load_profile(); |
|
284 for (let i = 0; i < 10; ++i) { |
|
285 let uri = NetUtil.newURI("http://hither.com/"); |
|
286 Services.cookies.setCookieString(uri, null, "oh" + i + "=hai; max-age=1000", |
|
287 null); |
|
288 } |
|
289 for (let i = 10; i < 3000; ++i) { |
|
290 let uri = NetUtil.newURI("http://haithur.com/"); |
|
291 Services.cookies.setCookieString(uri, null, "oh" + i + "=hai; max-age=1000", |
|
292 null); |
|
293 } |
|
294 |
|
295 // Close the profile. |
|
296 do_close_profile(sub_generator); |
|
297 yield; |
|
298 |
|
299 // Corrupt the database file. |
|
300 let size = do_corrupt_db(do_get_cookie_file(profile)); |
|
301 |
|
302 // Load the profile. |
|
303 do_load_profile(); |
|
304 |
|
305 // At this point, the database connection should be open. Ensure that it |
|
306 // succeeded. |
|
307 do_check_false(do_get_backup_file(profile).exists()); |
|
308 |
|
309 // Synchronously read in the cookies for our two domains. The first should |
|
310 // succeed, but the second should fail midway through, resulting in none of |
|
311 // those cookies being present. |
|
312 do_check_eq(Services.cookiemgr.countCookiesFromHost("hither.com"), 10); |
|
313 do_check_eq(Services.cookiemgr.countCookiesFromHost("haithur.com"), 0); |
|
314 |
|
315 // Wait for the backup file to be created and the database rebuilt. |
|
316 do_check_false(do_get_backup_file(profile).exists()); |
|
317 new _observer(sub_generator, "cookie-db-rebuilding"); |
|
318 yield; |
|
319 do_execute_soon(function() { do_run_generator(sub_generator); }); |
|
320 yield; |
|
321 |
|
322 // Close the profile. |
|
323 do_close_profile(sub_generator); |
|
324 yield; |
|
325 let db = Services.storage.openDatabase(do_get_cookie_file(profile)); |
|
326 do_check_eq(do_count_cookies_in_db(db, "hither.com"), 10); |
|
327 do_check_eq(do_count_cookies_in_db(db), 10); |
|
328 db.close(); |
|
329 |
|
330 // Check that the original database was renamed. |
|
331 do_check_true(do_get_backup_file(profile).exists()); |
|
332 do_check_eq(do_get_backup_file(profile).fileSize, size); |
|
333 |
|
334 // Rename it back, and try loading the entire database synchronously. |
|
335 do_get_backup_file(profile).moveTo(null, "cookies.sqlite"); |
|
336 do_load_profile(); |
|
337 |
|
338 // At this point, the database connection should be open. Ensure that it |
|
339 // succeeded. |
|
340 do_check_false(do_get_backup_file(profile).exists()); |
|
341 |
|
342 // Synchronously read in everything. |
|
343 do_check_eq(do_count_cookies(), 0); |
|
344 |
|
345 // Wait for the backup file to be created and the database rebuilt. |
|
346 do_check_false(do_get_backup_file(profile).exists()); |
|
347 new _observer(sub_generator, "cookie-db-rebuilding"); |
|
348 yield; |
|
349 do_execute_soon(function() { do_run_generator(sub_generator); }); |
|
350 yield; |
|
351 |
|
352 // Close the profile. |
|
353 do_close_profile(sub_generator); |
|
354 yield; |
|
355 let db = Services.storage.openDatabase(do_get_cookie_file(profile)); |
|
356 do_check_eq(do_count_cookies_in_db(db), 0); |
|
357 db.close(); |
|
358 |
|
359 // Check that the original database was renamed. |
|
360 do_check_true(do_get_backup_file(profile).exists()); |
|
361 do_check_eq(do_get_backup_file(profile).fileSize, size); |
|
362 |
|
363 // Clean up. |
|
364 do_get_cookie_file(profile).remove(false); |
|
365 do_get_backup_file(profile).remove(false); |
|
366 do_check_false(do_get_cookie_file(profile).exists()); |
|
367 do_check_false(do_get_backup_file(profile).exists()); |
|
368 do_run_generator(generator); |
|
369 } |
|
370 |
|
371 function run_test_4(generator) |
|
372 { |
|
373 // Load the profile and populate it. |
|
374 do_load_profile(); |
|
375 for (let i = 0; i < 3000; ++i) { |
|
376 let uri = NetUtil.newURI("http://" + i + ".com/"); |
|
377 Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); |
|
378 } |
|
379 |
|
380 // Close the profile. |
|
381 do_close_profile(sub_generator); |
|
382 yield; |
|
383 |
|
384 // Corrupt the database file. |
|
385 let size = do_corrupt_db(do_get_cookie_file(profile)); |
|
386 |
|
387 // Load the profile. |
|
388 do_load_profile(); |
|
389 |
|
390 // At this point, the database connection should be open. Ensure that it |
|
391 // succeeded. |
|
392 do_check_false(do_get_backup_file(profile).exists()); |
|
393 |
|
394 // Synchronously read in the first cookie. This will cause it to go into the |
|
395 // cookie table, whereupon it will be written out during database rebuild. |
|
396 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); |
|
397 |
|
398 // Queue up an INSERT for the same base domain. This should also go into |
|
399 // memory and be written out during database rebuild. |
|
400 let uri = NetUtil.newURI("http://0.com/"); |
|
401 Services.cookies.setCookieString(uri, null, "oh2=hai; max-age=1000", null); |
|
402 |
|
403 // Wait for the asynchronous read to choke and the insert to fail shortly |
|
404 // thereafter, at which point the backup file will be created and the database |
|
405 // rebuilt. |
|
406 new _observer(sub_generator, "cookie-db-rebuilding"); |
|
407 yield; |
|
408 do_execute_soon(function() { do_run_generator(sub_generator); }); |
|
409 yield; |
|
410 |
|
411 // Close the profile. |
|
412 do_close_profile(sub_generator); |
|
413 yield; |
|
414 |
|
415 // Check that the original database was renamed. |
|
416 do_check_true(do_get_backup_file(profile).exists()); |
|
417 do_check_eq(do_get_backup_file(profile).fileSize, size); |
|
418 let db = Services.storage.openDatabase(do_get_cookie_file(profile)); |
|
419 do_check_eq(do_count_cookies_in_db(db, "0.com"), 2); |
|
420 db.close(); |
|
421 |
|
422 // Load the profile, and check that it contains the new cookie. |
|
423 do_load_profile(); |
|
424 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 2); |
|
425 do_check_eq(do_count_cookies(), 2); |
|
426 |
|
427 // Close the profile. |
|
428 do_close_profile(sub_generator); |
|
429 yield; |
|
430 |
|
431 // Clean up. |
|
432 do_get_cookie_file(profile).remove(false); |
|
433 do_get_backup_file(profile).remove(false); |
|
434 do_check_false(do_get_cookie_file(profile).exists()); |
|
435 do_check_false(do_get_backup_file(profile).exists()); |
|
436 do_run_generator(generator); |
|
437 } |
|
438 |
|
439 function run_test_4(generator) |
|
440 { |
|
441 // Load the profile and populate it. |
|
442 do_load_profile(); |
|
443 for (let i = 0; i < 3000; ++i) { |
|
444 let uri = NetUtil.newURI("http://" + i + ".com/"); |
|
445 Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); |
|
446 } |
|
447 |
|
448 // Close the profile. |
|
449 do_close_profile(sub_generator); |
|
450 yield; |
|
451 |
|
452 // Corrupt the database file. |
|
453 let size = do_corrupt_db(do_get_cookie_file(profile)); |
|
454 |
|
455 // Load the profile. |
|
456 do_load_profile(); |
|
457 |
|
458 // At this point, the database connection should be open. Ensure that it |
|
459 // succeeded. |
|
460 do_check_false(do_get_backup_file(profile).exists()); |
|
461 |
|
462 // Synchronously read in the first cookie. This will cause it to go into the |
|
463 // cookie table, whereupon it will be written out during database rebuild. |
|
464 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); |
|
465 |
|
466 // Queue up an INSERT for the same base domain. This should also go into |
|
467 // memory and be written out during database rebuild. |
|
468 let uri = NetUtil.newURI("http://0.com/"); |
|
469 Services.cookies.setCookieString(uri, null, "oh2=hai; max-age=1000", null); |
|
470 |
|
471 // Wait for the asynchronous read to choke and the insert to fail shortly |
|
472 // thereafter, at which point the backup file will be created and the database |
|
473 // rebuilt. |
|
474 new _observer(sub_generator, "cookie-db-rebuilding"); |
|
475 yield; |
|
476 do_execute_soon(function() { do_run_generator(sub_generator); }); |
|
477 yield; |
|
478 |
|
479 // At this point, the cookies should still be in memory. |
|
480 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 2); |
|
481 do_check_eq(do_count_cookies(), 2); |
|
482 |
|
483 // Close the profile. |
|
484 do_close_profile(sub_generator); |
|
485 yield; |
|
486 |
|
487 // Check that the original database was renamed. |
|
488 do_check_true(do_get_backup_file(profile).exists()); |
|
489 do_check_eq(do_get_backup_file(profile).fileSize, size); |
|
490 let db = Services.storage.openDatabase(do_get_cookie_file(profile)); |
|
491 do_check_eq(do_count_cookies_in_db(db, "0.com"), 2); |
|
492 db.close(); |
|
493 |
|
494 // Load the profile, and check that it contains the new cookie. |
|
495 do_load_profile(); |
|
496 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 2); |
|
497 do_check_eq(do_count_cookies(), 2); |
|
498 |
|
499 // Close the profile. |
|
500 do_close_profile(sub_generator); |
|
501 yield; |
|
502 |
|
503 // Clean up. |
|
504 do_get_cookie_file(profile).remove(false); |
|
505 do_get_backup_file(profile).remove(false); |
|
506 do_check_false(do_get_cookie_file(profile).exists()); |
|
507 do_check_false(do_get_backup_file(profile).exists()); |
|
508 do_run_generator(generator); |
|
509 } |
|
510 |
|
511 function run_test_5(generator) |
|
512 { |
|
513 // Load the profile and populate it. |
|
514 do_load_profile(); |
|
515 let uri = NetUtil.newURI("http://bar.com/"); |
|
516 Services.cookies.setCookieString(uri, null, "oh=hai; path=/; max-age=1000", |
|
517 null); |
|
518 for (let i = 0; i < 3000; ++i) { |
|
519 let uri = NetUtil.newURI("http://" + i + ".com/"); |
|
520 Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null); |
|
521 } |
|
522 |
|
523 // Close the profile. |
|
524 do_close_profile(sub_generator); |
|
525 yield; |
|
526 |
|
527 // Corrupt the database file. |
|
528 let size = do_corrupt_db(do_get_cookie_file(profile)); |
|
529 |
|
530 // Load the profile. |
|
531 do_load_profile(); |
|
532 |
|
533 // At this point, the database connection should be open. Ensure that it |
|
534 // succeeded. |
|
535 do_check_false(do_get_backup_file(profile).exists()); |
|
536 |
|
537 // Synchronously read in the first two cookies. This will cause them to go |
|
538 // into the cookie table, whereupon it will be written out during database |
|
539 // rebuild. |
|
540 do_check_eq(Services.cookiemgr.countCookiesFromHost("bar.com"), 1); |
|
541 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); |
|
542 |
|
543 // Wait for the asynchronous read to choke, at which point the backup file |
|
544 // will be created and a new connection opened. |
|
545 new _observer(sub_generator, "cookie-db-rebuilding"); |
|
546 yield; |
|
547 |
|
548 // At this point, the cookies should still be in memory. (Note that these |
|
549 // calls are re-entrant into the cookie service, but it's OK!) |
|
550 do_check_eq(Services.cookiemgr.countCookiesFromHost("bar.com"), 1); |
|
551 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); |
|
552 do_check_eq(do_count_cookies(), 2); |
|
553 do_check_true(do_get_backup_file(profile).exists()); |
|
554 do_check_eq(do_get_backup_file(profile).fileSize, size); |
|
555 do_check_false(do_get_rebuild_backup_file(profile).exists()); |
|
556 |
|
557 // Open a database connection, and write a row that will trigger a constraint |
|
558 // violation. |
|
559 let db = new CookieDatabaseConnection(do_get_cookie_file(profile), 4); |
|
560 db.insertCookie(cookie); |
|
561 do_check_eq(do_count_cookies_in_db(db.db, "bar.com"), 1); |
|
562 do_check_eq(do_count_cookies_in_db(db.db), 1); |
|
563 db.close(); |
|
564 |
|
565 // Wait for the rebuild to bail and the database to be closed. |
|
566 new _observer(sub_generator, "cookie-db-closed"); |
|
567 yield; |
|
568 |
|
569 // Check that the original backup and the database itself are gone. |
|
570 do_check_true(do_get_rebuild_backup_file(profile).exists()); |
|
571 do_check_true(do_get_backup_file(profile).exists()); |
|
572 do_check_eq(do_get_backup_file(profile).fileSize, size); |
|
573 do_check_false(do_get_cookie_file(profile).exists()); |
|
574 |
|
575 // Check that the rebuild backup has the original bar.com cookie, and possibly |
|
576 // a 0.com cookie depending on whether it got written out first or second. |
|
577 db = new CookieDatabaseConnection(do_get_rebuild_backup_file(profile), 4); |
|
578 do_check_eq(do_count_cookies_in_db(db.db, "bar.com"), 1); |
|
579 let count = do_count_cookies_in_db(db.db); |
|
580 do_check_true(count == 1 || |
|
581 count == 2 && do_count_cookies_in_db(db.db, "0.com") == 1); |
|
582 db.close(); |
|
583 |
|
584 do_check_eq(Services.cookiemgr.countCookiesFromHost("bar.com"), 1); |
|
585 do_check_eq(Services.cookiemgr.countCookiesFromHost("0.com"), 1); |
|
586 do_check_eq(do_count_cookies(), 2); |
|
587 |
|
588 // Close the profile. We do not need to wait for completion, because the |
|
589 // database has already been closed. |
|
590 do_close_profile(); |
|
591 |
|
592 // Clean up. |
|
593 do_get_backup_file(profile).remove(false); |
|
594 do_get_rebuild_backup_file(profile).remove(false); |
|
595 do_check_false(do_get_cookie_file(profile).exists()); |
|
596 do_check_false(do_get_backup_file(profile).exists()); |
|
597 do_check_false(do_get_rebuild_backup_file(profile).exists()); |
|
598 do_run_generator(generator); |
|
599 } |
|
600 |